void*vs. char*指针算术

de1*_*7ed 10 c math pointers

我正在查看我的教科书,我对那里的一些代码感到有些困惑.在一个部分中,它们以下列方式执行指针运算:

void* bp;
...
bp = (void*)((char*)(bp)+16);
...
Run Code Online (Sandbox Code Playgroud)

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

void* bp;
...
bp = bp+16;
...
Run Code Online (Sandbox Code Playgroud)

我觉得它们应该是两个不同的东西,但它们就像对待它一样.我觉得这样,因为,例如,如果您要进行数组访问(例如,对于整数数组),您将执行以下操作

int* a = malloc(n*sizeof(int));
...
q = *(a+1);
...
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我不是访问整数数组中的下4个字节而不是下一个字节吗?同样,我觉得如果我有void*a,那么*(a + 1)应该是接下来的4个字节......或者不是这样的情况?谢谢.

Dan*_*her 14

这是一个漏洞.算术开void *不是由标准定义的,但是一些编译器将它作为扩展提供,其行为与char *算术相同.第二个是正式无效的C,但大概是出于(坏)习惯.


Ant*_*REL 7

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

尽管 (void *) 和 (char *) 都可以等效地转换为任何其他指针类型,但如果要遵守标准 C,则仅对 (char *) 执行指针算术才是合法的,而不是对 (void *) 执行指针算术。

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

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

gcc -ansi -pedantic -Wall -Wextra -Werror <more args...>
Run Code Online (Sandbox Code Playgroud)

我的底线是:

  • 如果要执行指针算术:使用 (char *)
  • 如果您想获取指针地址以便稍后将其转换为另一种类型:使用 (void *)

  • @AntoninGAVREL -- _“为了符合标准 C,您可以使用以下标志...”_ `-ansi` 标志编译为 C89,但您也可以使用 `-std=` 在其他标准下编译,例如 `-std=c17` 在 C17 下编译。 (2认同)