数组和指针

本文详细解析了数组与指针之间的转换规则,包括数组访问的底层实现原理、数组作为函数参数时的行为特性以及多维数组的转换方式,并强调了在不同文件间声明一致性的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组被转换为指针情况的总结:

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,访问新地址值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值