数组被转换为指针情况的总结:
1,使用a[i]这样的形式对数组进行访问总是被编译器改写为*(a+i)这样的指针访问。
这时候,在访问数组元素时,在连续的内存地址上移动时,编译器都必须计算每次前进的步长。计算的方法是偏移量乘以每个数组占用的字节数,计算结果就是偏移数组起始地址的实际字节数。步长因子常常是2的幂,(如int是4个字节,double是8个字节),这样编译器在计算是就可以使用快速的左移位运算,而不是相对缓慢的加法运算。
2,指针始终是指针,它绝对不可以改写成数组,可以用下表形式访问指针,一般都是指针作为函数的参数时,而且知道实际传递的是一个数组。
3,当把数组作为函数参数时,这个数组参数始终被编译器看作是一个指向数组第一个元素的指针。
例如:
void fun(char a[])
{
printf("%d/n",sizeof(a));//打印结果为4,即把a当做指针来看待。
}
4,函数参数传递多维数组时,编译器有以下转换:
数组的数组:实参char c[8][10];被转换为:char(*c)[10]; 数组指针
指针数组:实参char *c[15];被转换为:char **c;指针的指针
实参是char(*c)[]和char**时不进行转换。
总之转换基于一点:一维数组被转换为指向一维数组第一个元素的指针。
不能转换的情况:
如果在一个文件定义了一个数组(或指针),在其他文件对它进行声明时也必须把它声明为数组(或指针),必须严格匹配。
例:
//file1.c
char p[10] ={'c'};
//file2.c
int main()
{
extern char *p;
printf("%d/n",p);//打印结果为99(‘c’)
}
原因:这里的p被当作指针来处理,和定义的数组地址完全不一样,编译器处理时,按以下步骤处理:
1,在符号表中取p的地址,然后再提取存于此处的指针值(因为要打印p的值),此时为p[0],即为99('c')
p的地址在file1的导出符号表中,表示的是数组首地址。而对于编译单元file2来说,它认为p是一个指针,当它在file1的导出符号表中找到p的地址时,还要取出该地址中的值作为p的值。
2,把下标表示的偏移量与指针相加,产生一个新地址
3,访问新地址值。
本文详细解析了数组与指针之间的转换规则,包括数组访问的底层实现原理、数组作为函数参数时的行为特性以及多维数组的转换方式,并强调了在不同文件间声明一致性的重要性。
1729

被折叠的 条评论
为什么被折叠?



