如何通过数组指针在foo()中正确访问数组元素并避免栈溢出?
#include <stdio.h> void foo (int (*ptr)[10]) { (*ptr[0])++; (*ptr[1])++; (*ptr[4])++; } int main(int argc, char **argv) { int i; int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; foo(&arr); for (i = 0; i < 10; i++) { printf ("%d ", arr[i]); } printf ("\n"); return 0; }
编译运行输出:
vm@ubuntu:~/src/tcpip_stack$ gcc test.c vm@ubuntu:~/src/tcpip_stack$ ./a.out 2 2 3 4 5 6 7 8 9 10 *** 检测到栈溢出 ***: 已终止 已中止 (核心已转储)
问题分析
出错的核心是运算符优先级:数组下标[]的优先级高于解引用*,导致代码逻辑和预期完全偏离。
*ptr[0]等价于*(ptr[0]):ptr是指向10个int数组的指针,ptr[0]就是原数组(退化为首元素指针),所以这部分实际是修改arr[0],结果正确。*ptr[1]等价于*(ptr[1]):ptr[1]是ptr + 1,会跳过整个10-int数组,指向栈上原数组之外的内存,修改这块越界内存直接触发栈溢出。*ptr[4]同理,会跳过4个10-int数组的长度,越界程度更严重。
正确的访问方式
必须先解引用数组指针得到原数组,再用下标访问元素,也就是(*ptr)[index]的形式:
修改后的foo函数:
void foo (int (*ptr)[10]) { (*ptr)[0]++; // 对应 arr[0]++ (*ptr)[1]++; // 对应 arr[1]++ (*ptr)[4]++; // 对应 arr[4]++ }
修改后编译运行,输出为:
2 3 3 4 6 6 7 8 9 10
无栈溢出错误。
可选写法(指针算术)
也可以用指针偏移的方式访问,可读性稍差但逻辑等价:
void foo (int (*ptr)[10]) { (*(*ptr))++; // 等价于 (*ptr)[0]++ (*(*ptr + 1))++; // 等价于 (*ptr)[1]++ (*(*ptr + 4))++; // 等价于 (*ptr)[4]++ }
内容的提问来源于stack exchange,提问作者Abhishek Sagar
相关产品推荐
相关产品推荐

