指针C中的空指针的指针运算
当一个指向特定types(比如int , char , float ,…)的指针递增时,它的值就会增加该数据types的大小。 如果一个指向大小为x数据的void指针递增,它如何指向前面的x个字节? 编译器如何知道将x添加到指针的值? 
 最后的结论:在void*上的算术在C和C ++都是非法的 。 
  GCC允许它作为扩展,参见void函数指针上的算术 (请注意,本节是本手册“C扩展”一章的一部分)。 为了与GCC兼容,Clang和ICC可能允许void*算术。 其他编译器(例如MSVC)不允许对void*算术运算,如果指定了-pedantic-errors标志,或者指定了-Werror-pointer-arith标志,GCC将不允许使用该标志(如果你的代码库也必须用MSVC编译)。 
C标准讲话
行情来自n1256草案。
标准对加法操作的描述如下:
6.5.6-2:另外,两个操作数都应该有算术types,或者一个操作数应该是一个指向对象types的指针,另一个操作数应该是整型。
 所以,这里的问题是void*是否是指向“对象types”的指针,或者等价于void是否是“对象types”。  “对象types”的定义是: 
6.2.5.1types被划分为对象types (完全描述对象的types ), 函数types (描述函数的types)和不完整types (描述对象的types,但缺less确定其大小所需的信息)。
 标准将void定义为: 
6.2.5-19:
voidtypes包含一组空值; 这是一个不完整的types,不能完成。
 由于void是一个不完整的types,它不是一个对象types。 因此它不是一个加法操作的有效操作数。 
 因此你不能在void指针上执行指针运算。 
笔记
 原来,由于C标准的这些部分,认为void*算术是被允许的: 
6.2.5-27:指向void的指针与指向字符types的指针具有相同的表示和alignment要求。
然而,
相同的表示和alignment要求旨在将可互换性作为参数,从函数返回值以及联合成员。
 所以这意味着printf("%s", x)具有相同的含义,无论xtypes是char*还是void* ,但这并不意味着您可以对void*进行算术运算。 
编者按:这个答案已经被编辑,以反映最后的结论。
 指针运算在void*指针上是不允许的。 
 正因为如此,你不能在void *types上做指针运算。 
将其转换为char指针,将指针向前增加x个字节。
在做指针运算之前,你必须把它转换成另一种types的指针。
空指针可以指向任何内存块。 因此,当我们尝试在void指针上进行指针运算时,编译器不知道要增加或减less多less个字节。 因此,void指针必须首先被转换为一个已知types,然后才能涉及任何指针运算。
 void *p = malloc(sizeof(char)*10); p++; //compiler does how many where to pint the pointer after this increment operation char * c = (char *)p; c++; // compiler will increment the c by 1, since size of char is 1 byte. 
 编译器通过types转换知道。 给定一个void *x : 
-   x+1向x增加一个字节,指针转到字节x+1
-   (int*)x+1添加sizeof(int)字节,指针转到字节x + sizeof(int)
-   (float*)x+1地址sizeof(float)字节等
尽pipe第一项不是可移植的,并且不符合C / C ++的Galateo,但它仍然是C语言正确的,这意味着它将编译成大多数编译器上的某些东西,可能需要适当的标志(如-Wpointer-arith)
  C标准不允许void指针算术。 但是,考虑到void的大小是1允许GNU C。 
C11标准§6.2.5
第19段
voidtypes包含一组空值; 这是一个不完整的对象types,不能完成。
下面的程序在GCC编译中工作正常。
 #include<stdio.h> int main() { int arr[2] = {1, 2}; void *ptr = &arr; ptr = ptr + sizeof(int); printf("%d\n", *(int *)ptr); return 0; } 
可能是其他编译器产生错误。