本贴发于CSDN中的C语言讨论区,现转载于此,希望更多的人可以看到,写的不错。
主要是依据以下关于数组名和指针互相转换的道理:
(1)当一个数组标识符出现在表达式中,这个标识符的类型就从“某种类型T的数组”转换成“指向类型T的指针”,而且它的值就等于数组第一个元素的地址。并且这个指针是个常量指针,不可改变其值的。
(2)但是当数组标识符被用作sizeof和取址(&)操作的操作数时,sizeof返回的是整个数组的大小,而取址操作返回的是指向数组的指针(而不是指向一个值为数组头元素地址的指针的指针)。
(3)既然数组标示符在表达式中被“转换为”指针用,那对于二维数组又是什么情况呢?对于一个二维数组如:int a[3][3], a是指向一维数组的指针;当进行一次a[i]这样的运算后所得到的值是一个指针,其所指对象是一个int类型,[]运算符的作用除了变址,还将一个行指针变为一个列指针;同理当进行一次&a[i]这样的运算后所得到的指针又是一个指向一维数组的指针,即行指针。
int a[3] = {1, 2, 3};
char **s;
char p[3][5] = {{'a', 'b', 'c', 'c','/0'},
{'d', 'e', 'f', 'f','/0'},
{'/0', '/0', '/0', '/0', '/0'}};
s = (char **)p;
printf("a: %p/n", a); //0012FF74:a在表达式里被转为int *,指向a[0]
printf("*&a: %p/n", *&a); //0012FF74:a首先是int *,对一个指针型变量取地址之后再取值就是它本身,所以结果同上一行
printf("&a: %p/n", &a); //0012FF74:&a返回的是数组指针,因为数组的地址同a[0]的地址,所以结果同上一行
printf("&a[0]: %p/n", &a[0]); //0012FF74:打印的a[0]同学的地址,所以结果同上一行
printf("a[0]: %p/n", a[0]); //00000001:把a[0]的值以双字的形式打印出来
printf("*a: %p/n", *a); //00000001:把*a里的值当指针打印出其地址。记住a在表达式里被转为int *,指向a[0],
//所以*a其实就是a[0],所以结果同上一行。
printf("p: %p/n", p); //0012FF60:p是指向一维数组的指针,这个语句是要打印该一维数组的地址,等于p[0][0]的地址
printf("&p: %p/n", &p); //0012FF60:打印二维数组p的地址,等于p[0][0]的地址,所以结果同上一行
printf("p[0]: %p/n", p[0]); //0012FF60:p[0]是一维数组的数组名,出现在表达式中作为char *使用。
//这个语句是要打印p[0]所指向的字符的地址,也就是p[0][0]的地址,所以结果同上一行
printf("&p[0]: %p/n", &p[0]); //0012FF60:打印一维数组p[0]的地址,等于p[0][0]的地址,所以结果同上一行
printf("p[1]: %p/n", p[1]); //0012FF65:一维数组名p[1]作为char *,指向p[1][0]。
//这个语句是要打印p[1][0]的地址,该地址等于p[0][0]的地址加5
printf("p[2]: %p/n", p[2]); //0012FF6A:一维数组名p[2]作为char *,指向p[2][0]。
//这个语句是要打印p[2][0]的地址,该地址等于p[1][0]的地址加5
printf("&p[0][0]: %p/n", &p[0][0]); //0012FF60:打印p[0][0]的地址
printf("&p[1][0]: %p/n", &p[1][0]); //0012FF65:打印p[1][0]的地址
printf("&p[2][0]: %p/n", &p[2][0]); //0012FF6A:打印p[2][0]的地址
printf("s的值: %p/n", s); //0012FF60:s的值等于p的值,因此等于p[0][0]的地址;
printf("s+1的值: %p/n", s+1); //0012FF64:s是指针的指针,因此s+1等于s的地址加4字节(32位系统);
printf("*s: %p/n", *s); //63636261:s是char **,*s就是char*。
//因此这句意思是把s指向的内存取4个字节(也就是p[0][0]到p[0][]3)作为char*,打印其值。
printf("以s的值为地址的内存里的内容:%s /n", s); //abcc :从s所指向的地址取出连续内存(遇到'/0'为止)作为字符串来打印。
printf("以s+1的值为地址的内存里的内容:%s /n", s+1); // :从s+1所指向的地址取字符串来打印。