嗨,我有一个关于C指针(特别是void *)的问题。
我正在使用void *指针,这些指针指向作为Vector实现的单元的任意内存块。这些blob是在堆上分配的。
我的问题是为什么赋值
void *dest = CVectorNth(cv, i);
void *src = CVectorNth(cv, i-1);
*(void **)dest = *(void **)src;不工作时
memmove(dest, src, elementSize);确实行得通。
为什么我需要使用memmove?在我的头中,我将指针的值更改为src所指向的地址。
我知道memmove是正确的方法,但现在我甚至想不出一个理由
dest = src;不会起作用
发布于 2013-05-23 17:58:32
*(void **)dest = *(void **)src;将dest和src解释为指向void*的指针,并将sizeof(void *)字节从src指向的位置复制到dest指向的位置。
memmove(dest, src, elementSize);将elementSize字节从src指向的位置移动到dest指向的位置。如果可能是elementSize == sizeof(void *),如果受影响的区域不重叠,并且src和dest都适当对齐,则两者将具有相同的效果。如果dest和src中的任何一个没有正确对齐,第一个将调用未定义的行为(如果受影响的区域重叠,则至少有一个区域可能不会正确对齐)。
如果您有一个特定的Element类型,您只需要将dest和src转换为适当的类型。
*(Element *)dest = *(Element *)src;以达到预期的效果。
发布于 2013-05-23 17:57:14
这是因为C语言遵循一种设计哲学,归根结底就是“你不会为你不需要的东西付费,你也不会得到你不想要的东西”。特别是,当您声明一个变量的类型为void*时,然后您请求一个可以指向任何内容的指针,而您得到的只是一个这样的指针;而不是指针+类型字段+所指向的对象的大小字段,因此编译器不知道您打算复制多少字节。
请注意,
dest = src;确实起作用了,但它并不像你期望的那样。它将dest重新指定为指向与src相同的事物,这意味着您现在对同一事物有两个名称(可能是内存泄漏)。这可能非常有用(除了泄漏),但它是一个非常浅的副本。
至于
*(void **)dest = *(void **)src;在大多数情况下,这是未定义的行为。当它工作时,它将src作为指向void*的指针,并将其赋值给dest指向的void*,所以它仍然是一个指针副本,尽管是间接的。
发布于 2013-05-23 17:56:57
有了两个指针,你可以这样做:
*(char*) dest = *(char*) src;
*(double*) dest = *(double*) src;
*(struct{char[50] a;}*) dest = *(struct{char[50] a;}*) src;等同于:
memcpy(dest, src, sizeof(char));但不幸的是,C中的指针并不知道其分配的大小。通过它的类型可以知道它的元素大小,但是任何数组的大小都是未知的。
https://stackoverflow.com/questions/16710633
复制相似问题