memcpy:警告:对‘void *’指针进行解引用

4
我使用read()函数从文件中读取40个字符,并需要从第10个字符偏移处复制20个字符。换句话说,我需要将第10到30个字符从原始内存地址复制到新的内存地址中。当我运行以下代码时,却出现了警告信息:warning: dereferencing ‘void *’ pointer
int main()
{
    void *buffer = malloc(40);
    int fd = open("example20.txt", O_RDONLY);
    printf("the value of fd is %d \n", fd);


/* read 40 characters from the file */ 
int bytes_read = read(fd, buffer, 40);

void *new_container = malloc(20);

/* copy from buffer, starting offset at 10 for length of 20 */
memcpy(new_container, &buffer[10], 20);
printf("new_container is %s \n", (char *) new_container);

return 0;
}

我想知道这个错误是什么意思,以及如何修复它?

编辑1:我发现了一个解决问题的方法:通过将缓冲区从void*转换为新的char*指针。

char *buffer2 = (char *) buffer;
memcpy(new_container, &buffer2[10], 20);

编辑2:我找到了一种在memcpy中使用void*指针的方法:memcpy(new_container, buffer+10, 20);这种方式中的变量"buffer"可以是void*类型

3个回答

7

修改这行代码

memcpy(new_container, &buffer[10], 20);

to

memcpy(new_container, (char *)buffer + 10, 20);

那是因为&buffer[10]的值等价于&(*(buffer + 10)),因为数组下标操作符的优先级高于地址操作符&。然而,buffervoid *类型,不能对void指针进行指针算术运算,因为没有大小信息。在buffer上使用类型转换操作符(char *)提供了必要的大小信息,使得(char *)buffer + 10等价于buffer + 10 * sizeof(char)或者变量buffer指向的缓冲区中第11个元素的地址。

6
警告是由于以下原因造成的:
&buffer[10]

void没有大小,而[]运算符需要一个具体的数据类型以便以定义的方式操作。这是警告的原因可能是由于你的编译器支持以unsigned char *方式支持void*(例如gcc支持此扩展)。但这并不是标准。因此会出现警告。

请将其改为:

void *buffer = malloc(40);

变成这样:

unsigned char *buffer = malloc(40);

感谢您的快速回复。我需要“缓冲区”成为一个void指针的原因是我的程序不能假设读取的是字符串/字符,有时可能会是mp3文件或其他格式。不知道我是否仍然可以将“缓冲区”设置为char类型? - TonyGW
@TonyGW你使用'unsigned char *'应该没有问题(而且你可能会发现长远来看更容易使用/调试)。 - WhozCraig
我找到了一种在memcpy中使用void指针的方法:memcpy(new_container, buffer+10, 20); 这种方式下,变量"buffer"可以是void类型。 - TonyGW
@TonyGW 你可以跳过警告(如果它确实存在的话),但是该语句的有效性仍然只能由扩展支持。buffer+10其中buffervoid*,没有具体类型可用于执行指针算术运算。gcc会这样做,但这不是标准的。为了符合标准,您需要使用一个有类型的指针或在算术运算之前将其强制转换为有类型的指针类型(请参见ajay的答案以获取此类转换,本答案仅使用有类型的指针)。 - WhozCraig

3
错误/警告是在第几行发生的。
memcpy(new_container, &buffer[10], 20);

在这里,您试图访问buffer的第11个元素。但由于buffer是一个void *类型,所以执行buffer[10]是无效的。

您需要将其定义为

char *buffer = malloc(40);

同样适用于new_container

char *buffer = (char*)malloc(40); - Iłya Bursov
2
@Lashane:不,Rohan的版本是正确的,你的是多余的,如果你在允许隐式int的编译器上忘记包括stdlib.h,则会导致微妙的错误。这是C语言,不是C ++。存在从void *到任何其他指针类型的隐式转换。实际了解C语言的人不会强制转换malloc的返回值。 - Ed S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接