C/C++----const的理解、左值&右值的理解

1.const的理解:

  • const 在實際編程中用得並不多,const 是 constant 的縮寫,意思是“恆定不變的”!它是定義只讀變量的關鍵字,或者說 const 是定義常變量的關鍵字。
  • 說 const 定義的是變量,但又相當於常量;說它定義的是常量,但又有變量的屬性,所以叫常變量。

用 const 定義常變量的方法很簡單,就在通常定義變量時前面加 const 即可,如:

const  int  a = 10;

const 和變量類型 int 可以互換位置,二者是等價的,即上條語句等價於:

int  const  a = 10;

1.const在C中:

#include <stdio.h>

const int A = 10;		// 使用const修飾的全局常變量,受到保護,不能修改

int main()
{

	const int B = 30;	//const修飾的局部常變量,可以修改,是僞常量
	int* p = (int*)&B;
	*p = 50;
	printf("*p = %d, B = %d \n", *p, B);

	//int* p_a = (int*)&A;
	//*p_a = 60;						# 這一行如果執行會報錯了
	//printf("*p_a = %d, A = %d \n", *p_a, A);

}

// 結果如下:

*p = 50, B = 50


2.const在C++中:

#include <iostream>
using namespace std;

int main() {


	const int B = 30;		//在C++中,是真常量,不能修改
	int* p = (int*)&B;
	*p = 50;
	printf("*p = %d, B = %d \n", *p, B);

	return 0;
}

// 以上結果如下:
*p = 50, B = 30

  • C++中工作的原理如下圖:

在這裏插入圖片描述

  • C++中會把const修飾的常量放在符號表中(這個感興趣的可以去百度,感覺又是一類概念),這個有點類似key & value的形式,一個key對應一個value,且不能再次修改了!
  • int* p = (int*)&B; 這句的含義是,系統會臨時開闢一塊內存空間,暫時叫tem變量,目前*p指向這個臨時空間
  • p = 50因爲p已經指向一個空間了,後續直接把這塊空間賦值即可,那*p最終的值爲50了
  • 如上過程如果還不太理解,請看:
#include <iostream>
using namespace std;

int main() {


	int B;					// 先定義一個變量,單並未初始化,系統會開闢一塊臨時內存空間
	int* p = &B;			// 將指針p指向這塊內存空間
	*p = 50;				// 對p指向的這塊內存空間賦值
	printf("*p = %d, B = %d \n", *p, B);


	return 0;
}


*p = 50, B = 50

2.左值 & 右值

左值是用來指明一個對象的表達式。最簡單的左值就是變量名稱。左值(lvalue)之所以稱爲“左”(以首字母爲 L,代表 left),是因爲一個左值表示一個對象,它可以出現在賦值運算符(assignment operator)的左邊,例如“左表達式=右表達式”。

其他表達式(那些表示一個值但不指明一個對象的),被類似地稱爲右值(rvalue)。右值是可以出現在賦值運算符右邊而不是左邊的表達式。例如,常量和算術表達式。

從一個左值中必定可以解析出對應對象的地址,除非該對象是位字段(bit-field)或者被聲明爲寄存器存儲類。生成左值的運算符包括下標運算符(subscript operator)[]和間接運算符(indirection operator)*,如下表所示(如果 array 已被聲明爲數組,而 ptr 被聲明爲指針變量)。

int a;
int b;

a = 3;
b = 4;
a = b;
b = a;

// 以下寫法不合法。
3= a;
a+b = 4;

在 c 語言中:

  • 通常來說,有名字的變量就是左值(如上面例子中的 a, b),而由運算操作(加減乘除,函數調用返回值等)所產生的中間結果(沒有名字)就是右值,如上的 3 + 4, a + b 等。
  • 我們暫且可以認爲:左值就是在程序中能夠尋值的東西,右值就是沒法取到它的地址的東西(不完全準確).

如上概念到了 c++ 中,就變得稍有不同:

  • 在 c++ 中,每一個表達式都會產生一個左值,或者右值,相應的,該表達式也就被稱作“左值表達式", “右值表達式”。
  • 對於基本數據類型來說(primitive types),左值右值的概念和 c 沒有太多不同,不同的地方在於自定義的類型,而且這種不同比較容易讓人混淆
  1. 對於基礎類型,右值是不可被修改的(non-modifiable),也不可被 const, volatile 所修飾(cv-qualitification ignored)

  2. 對於自定義的類型(user-defined types),右值卻允許通過它的成員函數進行修改。

反正我讀了好幾遍(C/C++初學者,如果是你大佬,請跳過),具體怎麼理解,看看一些案例吧!

在這裏插入圖片描述

看了好多博文,我個人的理解是,左值就是可以放在棧內的,右值是能追溯到堆內存地址的

表達式 是左值嗎
array[1] 是;一個數組元素是一個具有位置的對象
&array[1] 否;此對象的位置,並非一個具有位置的對象
ptr 是;此指針變量是一個具有位詈的對象
*ptr 是;指針所指的地方是一個具有位置的對象
ptr+1 否;此加法產生一個新的地址值,但不是一個對象
*ptr+l 否;此加法產生一個新的算術值,但不是一個對象

3.題目案例:

1.case1

#include<stdio.h>

int main()
{
    char name[20];
    char *adress;
    name="小明";   //錯誤的
    adress="南極";  //正確的
 }



  • name不能作爲左值!!!編譯器會認爲數組名作爲左值代表的是name的首元素的首地址,但是這個地址開始的一塊內存是一個整體,我們只能訪問數組的某個元素,而無法把數組數組當做一個整體來進行訪問。
  • 所以,我們可以把name[i]當左值,無法把name當左值。
  • 也可以這麼理解:name的內部是由很多小部分組成,我們只能通過訪問這些小部分來達到訪問 name的目的。

指針address本身就是上面講到的內存小部分了

2.case2

int a=1;
const int b=2, *ptr=&a;
b=20;           //錯誤:b被聲明爲const int
*ptr=10;        //錯誤:ptr被聲明爲const int的指針

在這個例子中,表達式 a、b、ptr 和 *ptr 都是左值。但是 b 和 *ptr 是常量左值。因爲 ptr 被聲明爲指向 const int 的指針,不能使用它修改它所指向的對象。

賦值運算左邊的操作數,以及任何自增或自減運算符(++ 和 --)的操作數,不僅應該是左值,還應該是可修改的左值。可修改的左值,其類型不可以被聲明爲限定符 const,並且可修改的左值不能是數組類型。如果可修改的左值所表示的對象是結構或聯合類型,那麼它的元素都不可以被聲明(不管是直接地或間接地)爲具有限定符 const 的類型。

文章來源:
https://blog.csdn.net/u013478518/article/details/72897548

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章