[英]Pointer arithmetic for void pointer in C
当指向特定类型(例如int
、 char
、 float
、 ..)的指针递增时,其值会增加该数据类型的大小。 如果指向大小为x
数据的void
指针递增,它如何指向前面的x
个字节? 编译器如何知道将x
添加到指针的值?
最终结论:对void*
算术在 C 和 C++ 中都是非法的。
GCC 允许将其作为扩展,参见 关于void
和函数指针的算术(注意本节是手册“C 扩展”一章的一部分)。 为了与 GCC 兼容,Clang 和 ICC 可能允许void*
算术。 其他编译器(例如 MSVC)不允许对void*
算术运算,如果指定了-pedantic-errors
标志,或者指定了-Werror-pointer-arith
标志(如果您的代码库也必须用 MSVC 编译)。
引自 n1256 草案。
该标准对加法运算的描述指出:
6.5.6-2:对于加法,要么两个操作数都为算术类型,要么一个操作数为指向对象类型的指针,另一个操作数为整数类型。
所以,这里的问题是void*
是否是指向“对象类型”的指针,或者等价地, void
是否是“对象类型”。 “对象类型”的定义是:
6.2.5.1:类型分为对象类型(完整描述对象的类型)、函数类型(描述函数的类型)和不完整类型(描述对象但缺少确定其大小所需的信息的类型)。
该标准将void
定义为:
6.2.5-19:
void
类型包含一组空值; 它是无法完成的不完整类型。
由于void
是不完整的类型,因此它不是对象类型。 因此,它不是加法运算的有效操作数。
因此,您不能对void
指针执行指针运算。
最初,人们认为void*
算术是允许的,因为 C 标准的这些部分:
6.2.5-27:指向 void 的指针应具有与指向字符类型的指针相同的表示和对齐要求。
然而,
相同的表示和对齐要求意味着作为函数的参数、函数的返回值和联合成员的可互换性。
所以这意味着printf("%s", x)
无论x
类型是char*
还是void*
都具有相同的含义,但这并不意味着您可以对void*
进行算术运算。
void*
指针上不允许进行指针运算。
将其强制转换为 char 指针,将您的指针向前增加 x 个字节。
C 标准不允许空指针算术。 但是,考虑到void的大小为1
, GNU C是允许的。
C11 标准 §6.2.5
第 19 段
void
类型包含一组空值; 它是无法完成的不完整对象类型。
以下程序在 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;
}
可能是其他编译器产生错误。
您不能对void *
类型进行指针运算,正是出于这个原因!
在进行指针运算之前,您必须将其转换为另一种类型的指针。
空指针可以指向任何内存块。 因此,当我们尝试对 void 指针进行指针算术时,编译器不知道要增加/减少多少字节。 因此,void 指针必须首先被类型转换为已知类型,然后才能参与任何指针运算。
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.
void 指针中不允许进行指针运算。
原因:指针算术与普通算术不同,因为它是相对于基址发生的。
解决方案:在算术时使用类型转换运算符,这将使执行指针算术的表达式的基本数据类型已知。 例如:point 是空指针
*point=*point +1; //Not valid
*(int *)point= *(int *)point +1; //valid
编译器通过类型转换知道。 给定一个void *x
:
x+1
向x
增加一个字节,指针指向字节x+1
(int*)x+1
添加sizeof(int)
个字节,指针指向字节x + sizeof(int)
(float*)x+1
地址sizeof(float)
字节等。尽管第一项是不可移植的,并且与 C/C++ 的 Galateo 背道而驰,但它仍然是 C 语言正确的,这意味着它可以在大多数编译器上编译为某些内容,可能需要一个适当的标志(如 -Wpointer-arith)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.