无效指针与其他指针类型的兼容性

时间:2019-07-17 07:17:58

标签: c pointers c11

C的一个熟悉功能是void*可以分配给任何指针变量或从任何指针变量分配。在C1的标准文档草案N1570中,该文档在6.3.2.3 Pointers中指定:

  

指向void的指针可以转换为任何对象类型的指针,也可以将其转换为任何对象类型的指针。指向任何对象类型的指针都可以转换为void指针,然后再返回;结果应等于原始指针。

但是6.2.7 Compatible type and composite type

  

所有引用相同对象或函数的声明均应具有兼容的类型;否则,行为是不确定的。

据我所知,该部分void*与其他指针类型兼容。所以:

int x = 5;
int *xp = &x;
void *vp = xp;

根据传统和6.3.2.3预期是完全有效的,但6.2.7似乎是未定义的行为。

我想念什么?

2 个答案:

答案 0 :(得分:4)

关键字:所有声明 ...

int x = 5;
int *xp = &x;
void *vp = xp;

这是三个声明,分别声明三个独立的对象:xxpvp

您引用的部分意思是如果一个文件说

extern int foo;

另一个文件说

extern double *foo;

该行为未定义,因为foo已被声明两次,类型不同。

答案 1 :(得分:1)

  

Q:但是,据我所知,该部分并没有说void*与其他指针类型///兼容   ...根据传统和6.3.2.3完全有效,但按照6.2.7似乎是未定义的行为。

6.2.7并没有说太多,而是指向6.7.6.1指针声明的进一步阅读,在这里我们可以找到相关的部分:

  

要使两个指针类型兼容,则两者必须具有相同的限定条件,并且都应是指向兼容类型的指针。

因此,void*int*不兼容,因为voidint不兼容。它们可能会指向兼容类型,而您可以在它们之间自由地转换

您发布的代码很好,因为它仅与指向的类型有关。由于指针类型不兼容而导致的未定义行为的示例可能是这样:

void* v;
int* p = *(int**)&v;

这里,指针本身的地址被强制转换为不兼容的类型。它实际上是void**类型,但是程序员告诉编译器将其视为int**,然后像读取int*一样读取内容。形式上,我们通过“左值访问”读取对象,该类型与存储在该位置的对象不兼容。

尽管在实践中,由于void*必须在不丢失信息的情况下与其他对象指针类型进行相互转换,所以几乎可以肯定它的大小和表示形式与对象指针相同。尽管C标准不能保证,但是正式威胁它为另一种类型是未定义的行为。

这与对象和strict aliasing有效类型的C概念有关。