c - C中void指针的指针运算

标签 c void-pointers pointer-arithmetic

当指向特定类型(例如 intcharfloat 等)的指针递增时,其值会增加该数据类型的大小。如果指向大小为 x 的数据的 void 指针递增,它如何指向前面 x 字节?编译器如何知道将 x 添加到指针的值?

最佳答案

最终结论:关于 void* 的算术在 C 和 C++ 中都是非法

GCC 允许将其作为扩展,请参阅 Arithmetic on void - and Function-Pointers (请注意,本节是手册“C 扩展”一章的一部分)。 Clang 和 ICC 可能允许 void*算术以与 GCC 兼容。其他编译器(例如 MSVC)不允许对 void* 进行算术运算,并且如果 -pedantic-errors 则 GCC 不允许它指定了标志,或者如果 -Werror=pointer-arith指定标志(如果您的代码库还必须使用 MSVC 编译,则此标志很有用)。

C 标准说话

引文取自 n1256 草案。

标准对加法运算的描述如下:

6.5.6-2: For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type.

所以,这里的问题是 void* 是否是一个指向“对象类型”的指针,或者等效地,是否 void是一种“对象类型”。 “对象类型”的定义是:

6.2.5.1: Types are partitioned into object types (types that fully describe objects) , function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).

该标准定义了void如:

6.2.5-19: The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

void是不完整类型,它不是对象类型。因此它不是加法运算的有效操作数。

因此您无法对 void 执行指针算术指针。

注释

最初,人们认为void*由于 C 标准的这些部分,算术是允许的:

6.2.5-27: A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.

但是,

The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.

所以这意味着printf("%s", x) x 是否具有相同的含义类型为char*void* ,但这并不意味着您可以对 void* 进行算术运算.

关于c - C中void指针的指针运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58446185/

相关文章:

c++ - 使用 void 指针的动态数组实现

c++ - 为什么 2 地址之间的差异不是元素大小的倍数

c - 从数组读取段错误(可能与 malloc/realloc 相关)

点击气球托盘图标

C - 动态地将 void 指针转换为结构

比较 void * 是否包含 0 个字节?

c# - C# 中的指针数学

c - 哪些 C 编译器有指针减法下溢?

c - 为什么 YACC 会出现此警告?

c - 确保编译器始终使用 SSE sqrt 指令