函数调用间void指针指向的值莫名变更问题求助
函数调用间void指针指向的值莫名变更问题求助
先看你代码里最核心的问题——void 不能直接做算术运算!* 而且你的array_sort函数设计缺了关键参数,导致传递给比较函数的地址完全错了。
拆解下你的问题:
你在array_sort里写A + i,但A是void*类型。C标准里void*没有明确的大小,直接对它做加减运算属于未定义行为(部分编译器比如GCC会默认按1字节偏移,但这不是标准行为)。而你的数组是double类型,每个元素占8字节,所以A + 1实际只偏移了1个字节,根本不是指向第二个double元素的正确地址!
举个实际例子:假设数组首地址是0x1000,第一个double占0x1000~0x1007,第二个元素的正确地址应该是0x1008。但你写A + 1得到的是0x1001,把这个地址传给num_ascending后,强制转成double*解引用,读的是0x1001~0x1008的内存,这完全不是你原来的第二个元素,值自然变成了随机的0(或者其他乱码)。
至于max的值没问题,是因为它初始指向A(正确的首地址),而你测试时可能还没触发max = A + i的更新,或者刚好i=0时的地址是对的,但本质上这个逻辑也是有问题的。
修复方案
- 给
array_sort添加一个元素大小参数,就像标准库的qsort那样,用来正确计算元素偏移; - 计算元素地址时,先把
void*转成char*(因为char是1字节,适合做字节级偏移),再乘以元素大小得到正确的元素地址。
修改后的array_sort代码:
void array_sort(void *A, int arr_size, size_t elem_size, int comparison(void *, void*)) { void *max = A; int i; for (i = 0; i < arr_size; i++) { // 正确计算第i个元素的地址:首地址 + i * 每个元素的字节数 void *current = (char*)A + i * elem_size; if (comparison(current, max) == -1) { max = current; } } // 这里可以补充你原本的交换逻辑,你之前删除了,核心问题已解决 }
调用时传入sizeof(double)作为元素大小:
double my_arr[] = {5.0, 1.0, 3.0, 2.0}; array_sort(my_arr, sizeof(my_arr)/sizeof(my_arr[0]), sizeof(double), num_ascending);
最后提个小建议:以后别直接对void*做算术运算,这是C里的常见坑,一定要先转成具体类型(比如char*或对应元素的指针类型)再操作。
备注:内容来源于stack exchange,提问作者SomethingLikeThat
相关产品推荐
相关产品推荐

