char* ,char** ,char a[],char* a[]的深刻含義
0 前言
C語言中由於指標的靈活性,導致指標能代替陣列使用,或者混合使用,這些導致了許多指標和陣列的迷惑。本文深入探究了指標和陣列,主要是容易混淆的字元陣列和字元指標。
1 陣列的本質
陣列是多個元素的集合,在記憶體中分佈在地址相連的單元中,所以可以通過其下標訪問不同單元的元素。
2 指標的本質
指標也是一種變數,只不過它的記憶體單元中儲存的是一個標識其他位置的地址。由於地址也是整數,在32位平臺下,指標預設為32位。
指標變數永遠是整型,因為它儲存的是地址。
3 指標的指向
指向的直接意思就是指標變數所儲存的地址指向的記憶體單元所儲存的資料型別。
int* p; //p變數儲存的地址所指向的記憶體單元中的資料型別為整型
4 字元陣列
本質意義:陣列中的元素是字元。
char str[10]={"hello world"};
- 當編譯器遇到這句時,會把str陣列中從第一個元素把hello world\0 逐個填入。
- 由於C語言中沒有真正的字串型別,可以通過字元陣列表示字串,因為它的元素地址是連續的,這就足夠了。
- C語言中規定陣列代表陣列所在記憶體位置的首地址,也是 str[0]的地址,即str = &str[0]。
- C語言中字串常量的本質表示其實是一個地址。(難點)
針對難點4
char* s;
s="China";
C語言中編譯器會給字串常量分配地址,如果 "China", 儲存在記憶體中的 0x3000 0x3001 0x3002 0x3003 0x3004 0x3005。s="China";
s ="China" = 0x3000;
。你把"China"
看作是字串,但是編譯器把它看作是地址0x3000
,即字串常量的本質表現是代表它的第一個字元的地址。
%s
的原理其實也是通過字串首地址輸出字串,printf("%s ", s);
傳給它的其實是s所儲存的字串的地址。
對於char str[10] = "hello";``printf("%s",str);
本質也是printf("%s", "hello"的首地址);
C語言中操作字串是通過它在記憶體中的儲存單元的首地址進行的,這是字串的終極本質。
5 char* 與char a[]
char *s; char a[ ];
s=a;
可以,但a=s;
不可以
C語言中陣列名可以複製給指標表示地址, 但是卻不能賦給陣列名,它是一個常量型別,所以不能修改。
char a[]="hello";
char *s=a;
for(int i=0; i<strlen(a); i++)
printf("%c",s[i]); //或printf("%c",*s++);
字元指標可以用 間接操作符 *取其內容,也可以用陣列的下標形式 [ ],陣列名也可以用 *操作,因為它本身表示一個地址。
char* 與char a[]的本質區別
當定義 char a[10]
時,編譯器會給陣列分配十個單元,每個單元的資料型別為字元;而定義char *s
時,這是個指標變數,只佔四個位元組,32位,用來儲存一個地址。
sizeof(a) = 10;
sizeof(s) = 4; //編譯器分配4個位元組32位的空間,這個空間中將要儲存地址。
6 char** 與char* a[]
char *a[];
由於[ ] 的優先順序高於* 所以a先和 [ ]結合,他還是一個數組,陣列中的元素才是char * ,前面講到char * 是一個變數,儲存的地址。char *a[ ] = {"China","French","America","German"};
陣列中的元素是字串,那麼sizeof(a) 是多少呢,有人會想到是五個單詞的佔記憶體中的全部位元組數 6+7+8+7 = 28;但是其實sizeof(a) = 16;為什麼,前面已經說到,字串常量的本質是地址,a 陣列中的元素為char * 指標,指標變數佔四個位元組,那麼四個元素就是16個位元組了。
char **s;
char **為二級指標,s儲存一級指標char *
的地址。