C语言数组与指针相关代码的运行结果及底层原理是什么?
C语言指针运算问题解答
题目代码
int a[5] = { 1, 3, 5, 7, 9 }; int *p = (int *)(&a + 1); printf("%d, %d", *(a + 1), *(p - 1));
可选答案
3, 9(正确答案)- 运行错误
3, 12, 1
逻辑拆解
1. *(a + 1)的计算逻辑
数组名a在表达式中默认退化为指向数组首元素的int*类型指针,a + 1就是从首元素地址往后偏移1个int类型的长度,对应数组的第二个元素a[1],解引用后取值就是3,这部分逻辑比较直观。
2. int *p = (int *)(&a + 1)和*(p - 1)的计算逻辑
这里的核心是区分a和&a的类型差异:
a是指向单个int元素的指针,偏移步长为sizeof(int)(通常为4字节)&a是指向整个长度为5的int数组的指针,类型为int (*)[5],偏移步长为整个数组的总大小,也就是5 * sizeof(int)(通常为20字节)
所以执行&a + 1运算时,会从数组a的起始地址往后偏移20字节,刚好落在数组最后一个元素a[4]的后一个地址,这个地址本身是合法的,只是不属于数组a的存储范围。
之后把这个地址强制转换为int*类型赋值给指针p,此时p的步长变回了sizeof(int)。
执行p - 1时,就是把p存储的地址往前偏移4字节,刚好指向数组最后一个元素a[4]的地址,解引用后取值就是9。
整个访问过程没有越界访问非法内存,所以不会出现运行错误,最终输出结果就是3, 9。
内容的提问来源于stack exchange,提问作者Coderon
相关产品推荐
相关产品推荐

