Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
void*与char*指针算法_C_Pointers_Pointer Arithmetic - Fatal编程技术网

void*与char*指针算法

void*与char*指针算法,c,pointers,pointer-arithmetic,C,Pointers,Pointer Arithmetic,我正在翻阅我的课本,对其中的一些代码有点困惑。在一部分中,他们以以下方式执行指针算法: void* bp; ... bp = (void*)((char*)(bp)+16); ... 但后来,他们做了以下工作: void* bp; ... bp = bp+16; ... ansi -pedantic -Wall -Wextra -Werror 我觉得他们应该是两个不同的东西,但他们对待它就像一个东西。 我这样认为是因为,例如,如果要进行数组访问(例如整数数组),您将执行以下操作 int*

我正在翻阅我的课本,对其中的一些代码有点困惑。在一部分中,他们以以下方式执行指针算法:

void* bp;
...
bp = (void*)((char*)(bp)+16);
...
但后来,他们做了以下工作:

void* bp;
...
bp = bp+16;
...
ansi -pedantic -Wall -Wextra -Werror
我觉得他们应该是两个不同的东西,但他们对待它就像一个东西。 我这样认为是因为,例如,如果要进行数组访问(例如整数数组),您将执行以下操作

int* a = malloc(n*sizeof(int));
...
q = *(a+1);
...
在这种情况下,我不是在访问整数数组中的下4个字节而不是下一个字节吗? 类似地,我觉得如果我有void*a,那么*(a+1)应该是接下来的4个字节。。。 还是不是这样?
谢谢。

这是个失误。标准没有定义void*上的算术,但一些编译器将其作为扩展提供,其行为与算术的char*相同。第二个答案在形式上是无效的,但可能是出于(坏)习惯而漏掉的。

公认的答案是一个很好的总结,我想更清楚地说明为什么要使用一个或另一个

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

为什么两者都用作指针?大多数指向(void*)和从(void*)的指针转换都可以不用强制转换来完成,但是(char*)的使用让人想起了过去

Gcc不会对(void*)上的指针算术发出警告,因为它不是旨在符合标准C的编译器,而是GNU C。要符合标准C,您可以使用以下命令:

void* bp;
...
bp = bp+16;
...
ansi -pedantic -Wall -Wextra -Werror
我的底线是:

  • 如果希望执行指针算术:使用(char*)
  • 如果希望获取指针地址以便稍后将其转换为其他类型,请使用(void*)

第二个示例不应编译。@OliCharlesworth:如果以一致模式编译,它将不会编译(或至少会触发警告)。默认情况下,gcc不符合要求,并将
void*
算法作为扩展实现。因此,访问下一个16字节的正确方法是首先强制转换为char*,然后添加16?哈哈,现在得修改很多代码了。哦,我把第一个抄错了一点,我做了一个小改动,但我认为这不会对我的问题产生影响。或者你可以转换到
uint64\u t*
并添加2;)是的,可移植的方法是将指针转换为已知大小的类型,并对其进行算术运算。如果您不需要可移植性,并且您的编译器文档
void*
算术以特定的方式工作,那么您可以使用它。但是,当然,在某个时候,您将不得不移植到另一个编译器。。。