C11 6.2.5 P28:
指向 void 的指针应与指向字符类型的指针具有相同的表示和对齐要求。 48) 同样,指向兼容类型的限定或非限定版本的指针应具有相同的表示和对齐要求。所有指向结构类型的指针应具有相同的表示和对齐要求。所有指向联合类型的指针应具有相同的表示和对齐要求。指向其他类型的指针不需要具有相同的表示或对齐要求。
48) 相同的表示和对齐要求意味着作为函数参数、函数返回值和联合成员的可互换性。
我的疑问来自Note 48。我不知道这里的“互换性”指的是什么,也没有找到它的官方定义。
我特别想知道“互换性”到底是什么? 为什么这里只提到函数的参数、函数的返回值和联合体的成员具有“互换性”?
换句话说,为什么标准没有说:“相同的表示和对齐要求意味着作为结构体成员的可互换性。”?
说实话,我见过有人举过这样的例子。但基本上他们都是按照这句话,然后举出他们认为的“可互换性”的例子,就好像你知道结果然后把结果补出来一样,他们没有解释为什么这三个是特殊的“可互换性”,也没有'先从根源上解释一下什么是“可互换性”。
有人可以解答我的上述疑惑吗?如果可以的话,您能举一个合适的例子吗? 感谢您的阅读。
注释不是标准的规范部分——它们是帮助读者解释标准的陈述,但不被视为标准官方规则的一部分。因此,您不应期望仅在注释中使用的单词有官方定义。它有其简单的英语含义:如果 A 和 B 可以互换,则意味着无论在哪里可以使用 A,都可以使用 B 来产生相同的效果/后果,反之亦然。
这不是标准的一个很好的部分,因为它不能按字面意思理解。例如,C 2018 6.2.5 28 告诉我们
void *
和 char *
应具有相同的表示和对齐要求,注释 49 告诉我们这意味着它们可以互换作为函数的返回值。但 C 2018 6.7 2 强加了一个约束,即函数的两个声明必须具有兼容的类型,违反此要求需要诊断消息,但两个函数类型仅当它们的返回类型兼容时才兼容 (6.7.6.3 15)。
考虑:
void *foo(void);
void *foo(void) { return 0; }
所以
void *
和 char *
实际上是不可互换的,因为上面的代码与将第一个 void *
更改为 char *
的相同代码会有不同的行为(编译器将给出诊断并且通常拒绝编译)。
实现可互换性的一种方式是,如果
foo
在一个翻译单元中声明为 char *foo(void);
并在另一个翻译单元中定义为 void *foo(void) { return 0; }
,那么该程序的工作方式应该与始终使用 void *
一样。但在注释中指定这种可互换性是将其纳入标准的一种粗略方法。起草该标准的委员会似乎想要说一些关于允许将其中一种类型用于另一种类型的事情,但没有正式的方式来编写它。