程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C 語言中的左值和右值。以及對比數組名和指針取數組元素的區別。

C 語言中的左值和右值。以及對比數組名和指針取數組元素的區別。

編輯:關於C語言

C 語言中的左值和右值。以及對比數組名和指針取數組元素的區別。


左值:出現在賦值符左邊的符號有時稱為左值。

右值:出現在賦值符右邊的符號有時稱為右值。

編譯器為每個變量分配一個地址(左值),這個地址在編譯時可知,而且該變量在運行時一直保存於這個地址。相反,存儲於變量中的值(它的右值)只有在運行時才可知。如果需要用到變量中存儲的值,編譯器就發出指令從指定地址讀入變量值並將它存於寄存器。

可以看到,每個符號的地址在編譯時可知。

對比一下幾個式子:

//常規變量

int a=1;//這裡a作為左值出現,代表的是地址,即在a表示的這個內存地址存入數值1。即a代表的內存地址這個地方的數據或是值,為1。

int b=a;//這裡a作為右值出現,代表的是數值,即a表示的這個內存地址上的數據,即數值1。

//指針

int *p=a;//這裡p作為左值出現,代表的是地址。把左邊看做一個整體,相當於在(*p)表示的內存地址的地方存入a的值,而p則是存的是(*p)所表示的地址。即p作為左值,本身代表一個內存地址,在該內存地址存的值即(*p)——是個數值,但該數值表示內存地址。然後在(*p)代表的內存地址地方存的是數值——即a的值。

int *pb=p;//這裡p作為右值出現,代表的是數值。即把p這個內存地址地方上的數值賦給pb內存地址,所以pb和p內存地址上數據相同,即指向了同一地方。

//char 數組

char arr[]="abcdefg";//這裡arr作為左值出現,代表的是地址。因為符號本身作為左值,代表的就是一個內存地址。所以,用數組名取元素時相當於對內存是直接引用。

printf("%s",arr);//這裡arr作為右值出現,代表的則是數值,即整個字符串。

對比數組名和指針取元素。數組名,就是一個內存地址。如果編譯器需要一個地址(可能還需要加上偏移量)來執行某種操作,它就可以直接進行操作,並不需要增加指令首先取得具體的地址。相反,對於指針,必須首先在運行時取得它的當前值,然後才能對它進行解除引用操作。數組是對內存直接引用,指針是對內存間接引用。

這樣的話,就可以理解下面代碼為什麼錯誤:

//file1

int a[10];

//file2

extern int *a;

即文件2希望用到文件1裡定義的一些變量。但是上述代碼是錯誤的。因為在文件1裡把a聲明為數組,實際上它是以直接引用的方式存取內存。而在文件2中把a外部聲明為指針,在a[i]進行取元素時,由於文件2看到的a是指針,則是對內存間接引用,則先取得a地址的數據,並把該數組作為地址再進行取數據,這樣當然是錯的。

以下是一些測試代碼:

可以看到數組名在printf函數中,作為右值出現時,如果是按%#x來打印的話,打印的還是地址。即按%#x打印,ga和&ga輸出的地址相同。(我的理解是,ga這個數組名本身代表的就是內存地址,作為右值出現時,是代表字符串,但這裡是按地址打印的;而&ga即取這個符號ga所在的地址。——解釋得不太好。)

但是對於指針,按%#x打印,指針名打出的是該地址的值(即指向地方的地址,因為指針作為右值出現,取的是值);取址指針名,即&指針名,打印的則是指針名代表的地址,即指針這個符號本身代表的地址。

#include
#include

void my_array_func(char ca[]);
void my_pointer_func(char *pa);

char ga[] = "abcdefghijklmn";

int main()
{
	printf(" ga = %#x \n",ga);
	printf(" addr of global array &ga = %#x \n", &ga);
	//printf(" &(&ga) = %#x \n", &(&ga));//(最左邊的)&必須是對左值進行操作
	printf(" ga c = %c\n",ga);
	printf(" ga s = %s\n",ga);
	printf(" addr (ga[0]) &(ga[0]) = %#x \n", &(ga[0]));
	printf(" addr (ga[1]) &(ga[1]) = %#x \n\n", &(ga[1]));
	my_array_func(ga);
	my_pointer_func(ga);

	system("pause");
	return 0;
}

void my_array_func(char ca[10]){
	printf(" addr of array param &ca = %#x \n",&ca);
	printf(" addr (ca[0]) &(ca[0]) = %#x \n",&(ca[0]));
	printf(" addr (ca[1]) &(ca[1]) = %#x \n",&(ca[1]));
	printf(" ca = %#x \n",ca);
	printf(" ++ca = %#x \n", ++ca);
}

void my_pointer_func(char *pa){
	printf(" addr of ptr param &pa = %#x \n",&pa);
	printf(" addr (pa[0]) &(pa[0]) = %#x \n",&(pa[0]));
	printf(" addr (pa[1]) &(pa[1]) = %#x \n",&(pa[1]));
	printf(" pa = %#x \n",pa);
	printf(" ++pa = %#x \n",++pa);
}
結果:

\




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved