如何解决取消引用指针会更改其值
我试图在c中实现生锈样式的矢量,
typedef struct
{
int *ptr,// pointer to starting element
int len,// length of the vector
int cap,// capacity; it does not reallocate the whole vector till len == cap
} vector;
除get-value函数外,我几乎所有工作正常。不管向量的长度如何,调用vec_getval函数始终会将第3个元素和第4个元素分别更改为1936877926和10。这是所有相关代码,省略了错误检查:
#define ELEMENT_SIZE sizeof(int)
extern vec_data vec_getval(vector *vec,size_t index)
{
return *(vec->ptr + (ELEMENT_SIZE * index));
}
extern void vec_push(vector *vec,vec_data val)
{
if (vec->len < vec->cap) // Don't reallocate if length < capacity
{
*(vec->ptr + (ELEMENT_SIZE * vec->len)) = val;
vec->len++;
return;
}
realloc(vec->ptr,ELEMENT_SIZE * (vec->len + 1));
*(vec->ptr + (ELEMENT_SIZE * vec->len)) = val;
vec->len++;
vec->cap++;
}
extern void vec_with_capacity(vector *vec,size_t cap)
{
vec->ptr = (int *)malloc(ELEMENT_SIZE * cap);
vec->cap = cap;
vec->len = 0;
}
int main(int argc,char **args)
{
vector vec;
vec_with_capacity(&vec,5);
vec_push(&vec,50u);
vec_push(&vec,15u);
vec_push(&vec,40u);
vec_push(&vec,80u);
vec_push(&vec,70u);
printf("first value\t: %d\n",vec_getval(&vec,0)); // Works as expected,but changes 3rd and 4th elements
printf("third value\t: %d\n",2)); // Does not work fine!
return 0;
}
这是输出:
first value : 50
third value : 1936877926
解决方法
对于任何指针或数组p
和索引i
,表达式*(p + i)
精确地等于p[i]
。
现在,如果我们对*(vec->ptr + (ELEMENT_SIZE * index)
进行此转换,则会得到vec->ptr[ELEMENT_SIZE * index]
。这可能与您的想法不符。
假设sizeof(int)
(ELEMENT_SIZE
的扩展名)是4
(非常常见),则尝试使用索引2
实际上将使用索引8
( 4 * 2
)。哪个超出了您分配的内存范围(因为它仅包含5
元素),并导致未定义的行为。
解决方案很简单:访问数组的元素时不要与ELEMENT_SIZE
相乘。
您还有另外两个非常严重的错误:
realloc(vec->ptr,ELEMENT_SIZE * (vec->len + 1))
*(vec->ptr + (ELEMENT_SIZE * vec->len)) = val;
由于第一行缺少分号,因此该语句变为
realloc(vec->ptr,ELEMENT_SIZE * (vec->len + 1)) * (vec->ptr + (ELEMENT_SIZE * vec->len)) = val;
那没有任何意义。
除了缺少分号之外,第二个问题是realloc
可以分配一个 new 内存区域,然后该内存区域返回一个指针。这将使旧指针无效,因为它随后指向您不再拥有的内存。始终使用realloc
返回的结果。
还要注意,realloc
可以返回NULL
,在这种情况下,旧指针仍然有效,因此请始终使用一个临时变量:
int *new_ptr = realloc(vec->ptr,ELEMENT_SIZE * (vec->len + 1));
if (new_ptr == NULL)
{
// TODO: Handle error
}
vec->ptr = new_ptr;
vec->ptr[vec->len] = val;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。