void* 与 char* 指针算术

问题描述 投票:0回答:2

我正在浏览我的教科书,我对其中的一些代码有点困惑。一方面,他们通过以下方式执行指针算术:

void* bp;
...
bp = (void*)((char*)(bp)+16);
...

但后来,他们做了以下事情:

void* bp;
...
bp = bp+16;
...

我觉得它们应该是两个不同的东西,但他们却把它当作同一件事。 我有这种感觉是因为,例如,如果您要进行数组访问(例如,对于整数数组),您将执行以下操作

int* a = malloc(n*sizeof(int));
...
q = *(a+1);
...

在这种情况下,我不是访问整数数组中的接下来的 4 个字节而不是下一个字节吗? 同样,我觉得如果我有

void* a
,那么
*(a+1)
应该是接下来的4个字节...... 或者事实并非如此?

c pointers void-pointers pointer-arithmetic char-pointer
2个回答
24
投票

这是一个失误。标准未定义

void *
上的算术,但某些编译器将其作为扩展提供,其行为与算术中的
char *
相同。第二个在形式上是无效的 C,但大概是出于(坏)习惯而漏掉的。


6
投票

接受的答案是一个很好的总结,我想更清楚地说明为什么要使用其中之一。 ;)

虽然 (void *) 和 (char *) 都可以等效地转换为任何其他指针类型,但 只有在 (char *) 上执行指针算术才合法,而不是 (void *) 如果您想遵守标准C.

为什么两者都用作指针?大多数与 (void *) 之间的指针转换都可以在不进行强制转换的情况下完成,但 (char *) 的使用让人回想起旧时代。

GCC 不会对 (void *) 上的指针算术发出警告,因为它不是一个旨在兼容标准 C 而是 GNU C 的编译器。要遵循标准 C,您可以使用以下标志:

gcc -ansi -pedantic -Wall -Wextra -Werror <more args...>

我的底线:

  • 如果你想执行指针运算:使用(char *)
  • 如果您想要 获取指针地址以便稍后将其转换为另一种类型:使用 (void *)
© www.soinside.com 2019 - 2024. All rights reserved.