先看 char *a [ ] ;數組
因爲[ ] 的優先級高於* 因此a先和 [ ]結合,他仍是一個數組,數組中的元素纔是char * ,前面講到char * 是一個變量,保存的地址。。3d
因此 char *a[ ] = {"China","French","America","German"};指針
同過這句能夠看到, 數組中的元素是字符串,那麼sizeof(a) 是多少呢,有人會想到是五個單詞的佔內存中的所有字節數 6+7+8+7 = 28;blog
可是其實sizeof(a) = 16;內存
爲何,前面已經說到, 字符串常量的本質是地址,a 數組中的元素爲char * 指針,指針變量佔四個字節,那麼四個元素就是16個字節了字符串
看一下實例:編譯器
#include <stdio.h>io
int main()
{
char *a [ ] = {"China","French","America","German"};
printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]);編譯
return 0;
}變量
能夠看到數組中的四個元素保存了四個內存地址,這四個地址中就表明了四個字符串的首地址,而不是字符串自己。。。
所以sizeof(a)固然是16了。。
注意這四個地址是不連續的,它是編譯器爲"China","French","America","German" 分配的內存空間的地址, 因此,四個地址沒有關聯。
#include <stdio.h>
int main()
{
char *a [ ] = {"China","French","America","German"};
printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]); //數組元素中保存的地址
printf("%p %p %p %p\n",&a[0],&a[1],&a[2],&a[3]);//數組元素單元自己的地址
return 0;
}
能夠看到 0012FF38 0012FF3C 0012FF40 0012FF44,這四個是元素單元所在的地址,每一個地址相差四個字節,這是因爲每一個元素是一個指針變量佔四個字節。。。
char **s;
char **爲二級指針, s保存一級指針 char *的地址,關於二級指針就在這裏不詳細討論了 ,簡單的說一下二級指針的易錯點。
舉例:
char *a [ ] = {"China","French","America","German"};
char **s = a;
爲何能把 a賦給s,由於數組名a表明數組元素內存的單元的首地址,即 a = &a[0] = 0012FF38;
而 0x12FF38即 a[0]中保存的又是 00422FB8 ,這個地址, 00422FB8爲字符串"China"的首地址。
即 *s = 00422FB8 = "China";
這樣即可以經過s 操做 a 中的數據
printf("%s",*s);
printf("%s",a[0]);
printf("%s",*a);
都是同樣的。。。
但仍是要注意,不能a = s,前面已經說到,a 是一個常量。。
再看一個易錯的點:
char **s = "hello world";
這樣是錯誤的,
由於 s 的類型是 char ** 而 "hello world "的類型是 char *
雖然都是地址, 可是指向的類型不同,所以,不能這樣用。,從其本質來分析,"hello world",表明一個地址,好比0x003001,這個地址中的內容是 'h'
,爲 char 型,而 s 也保存一個地址 ,這個地址中的內容(*s) 是char * ,是一個指針類型, 因此二者類型是不同的。 。。
若是是這樣呢?
char **s;
*s = "hello world";
貌似是合理的,編譯也沒有問題,可是 printf("%s",*s),就會崩潰
why??
咱來慢慢推敲一下。。
printf("%s",*s); 時,首先得有s 保存的地址,再在這個地址中找到 char * 的地址,即*s;
舉例:
s = 0x1000;
在0x1000所在的內存的單元中保存了"hello world"的地址 0x003001 , *s = 0x003001;
這樣printf("%s",*s);
這樣會先找到 0x1000,而後找到0x003001;
若是直接 char **s;
*s = "hello world";
s 變量中保存的是一個無效隨機不可用的地址, 誰也不知道它指向哪裏。。。。,*s 操做會崩潰。。
因此用 char **s 時,要給它分配一個內存地址。
char **s ;
s = (char **) malloc(sizeof(char**));
*s = "hello world";
這樣 s 給分配了了一個可用的地址,好比 s = 0x412f;
而後在 0x412f所在的內存中的位置,保存 "hello world"的首地址。。
再如:
#include <stdio.h>
void buf( char **s)
{
*s = "message";
}
int main()
{
char *s ;
buf(&s);
printf("%s\n",s);
}
二級指針的簡單用法,說白了,二級指針保存的是一級指針的地址,它的類型是指針變量,而一級指針保存的是指向數據所在的內存的單元的地址,雖然都是地址,可是類型是不同的