C语言通用向量实现问题:void指针拷贝整数/双精度值异常
问题排查与修复方案
你的向量实现中,整数和双精度类型出现异常的核心原因是内存分配逻辑错误和元素指针偏移计算错误,字符类型碰巧正常只是因为它的大小为1,刚好掩盖了这些问题。咱们逐一解决:
1. 内存分配的错误(v_push_back函数)
你当前的扩容代码错误地用指针大小计算总内存:
v->e_array = check_a(realloc(v->e_array, sizeof(void*) * v->cur_cap));
这里的问题在于,e_array是直接存储元素值的缓冲区,不是存储指针的数组,应该用每个元素的实际大小v->e_sz来计算总内存。比如int类型占4字节,按指针大小(通常8字节)分配会导致内存错位,最终读取出垃圾值。
修正后的扩容代码:
v->e_array = check_a(realloc(v->e_array, v->e_sz * v->cur_cap));
2. 元素指针偏移计算错误(v_at函数)
当前v_at的指针偏移逻辑完全错误:
return (v->e_array+i);
标准C不允许直接对void*做算术运算,而且即使编译器支持,步长也是1字节,但你的元素大小是v->e_sz,正确的偏移应该是i * v->e_sz,并且要先把v->e_array转换成char*类型(字节级指针)再计算偏移。
修正后的v_at函数:
void* v_at(vector_type v, iterator i) { if ( v == NULL ) fail("v_at() Error: no such vector"); if ( i == iterator_end ) i = v->no_e -1; if ( i < 0 || i >= v->no_e ) fail("v_at() Error: no such element in this vector"); return (char*)v->e_array + i * v->e_sz; // 转为char*后计算字节级偏移 }
3. 额外提示:循环传址的潜在问题
你在整数循环中直接传&i1的地址:
for ( i1 = 0 ; i1 < 10 ; i1++ ){ v_push_back(vi1,(void*)&i1); }
这会导致所有元素都指向同一个变量i1的地址,循环结束后i1的值是10,修复内存问题后你会发现所有输出都是10,而不是0到9。解决方法是每次创建临时变量:
for ( i1 = 0 ; i1 < 10 ; i1++ ){ int temp = i1; v_push_back(vi1,(void*)&temp); }
为什么字符类型正常?
因为char类型的e_sz是1字节,错误的偏移计算i(而非i*1)结果和正确值一致,内存分配时sizeof(void*)也大于等于1,所以没有暴露问题,但这只是巧合,不是正确实现。
内容的提问来源于stack exchange,提问作者Faizan Shah
相关产品推荐
相关产品推荐

