0

N2479 C17..C2x 工作草案 — 2020 年 2 月 5 日 ISO/IEC 9899:202x (E)(已添加重点):

6.7.2.1 结构和联合说明符

17 在结构对象中,非位域成员和位域所在的单元的地址按声明顺序递增。一个指向结构对象的指针,经过适当的转换,指向它的初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然。结构对象中可能有未命名的填充,但不是在其开头。

18 工会的规模足以容纳其最大的成员。任何时候最多可以将其中一个成员的值存储在联合对象中。一个指向联合对象的指针,经过适当的转换,指向它的每个成员(或者如果一个成员是一个位域,那么指向它所在的单元),反之亦然。

问题: 的确切定义是suitably converted什么?

额外:如果没有确切的定义suitably converted,那么 C 实现应该记录它的理解吗?例如(C/C++ 预处理器域),微软将术语single item(C++,N4713)理解为single, permanently indivisible preprocessor token(这会导致从 gcc/clang/other 移植代码时出现问题,这有不同的理解),但是,他们似乎没有记录他们对single item.

4

4 回答 4

3

在这种情况下,“适当的转换”意味着转换为适当的兼容类型。例如:

#include <stdio.h>

struct mystruct {
    double a;
    int b;
};

int main()
{
    struct mystruct s = { 2.5, 4 };
    double *d = (double *)&s;
    printf("%f\n", *d);   // prints 2.500000
    return 0;
}

这里的第一个成员struct mystructhas type double。因此,在这种情况下,“合适的转换”意味着 astruct mystruct *可以通过显式转换转换为double *,并将指向该a成员。

于 2021-03-19T19:17:48.920 回答
3

这不是一个具有特殊含义的术语。

您正在处理从类型 A 到类型 B 的转换。类型 A 是指向结构的类型。除了必须适合用作指向初始成员的指针外,未指定类型 B。因此,它必须是一个指针(所以我们只处理两种指针类型之间的转换)并且它必须遵循严格的别名规则(目标类型可以是指向窄字符类型的指针,std::byte第一个成员的实际类型,或表示兼容的类型,例如仅在符号上不同)。

导致合适指针的任何指针转换都满足“适当转换”。

于 2021-03-19T19:19:26.717 回答
2

问题:适当转换的确切定义是什么?

C 标准没有给出“适当转换”的任何“确切定义”。</p>

我将其解释为对“指向初始成员类型的指针”或“指向结构类型的指针”类型的任何转换序列,以便转换规范确保最终指针指向适当的地址。(例如,没有通过可能不正确对齐的转换。)

额外:如果没有适当转换的确切定义,那么C实现是否应记录其理解?

C 标准不要求 C 实现记录其对“适当转换”的理解或解释。</p>

于 2021-03-19T19:16:22.010 回答
0

这不是一个正式的术语,但在字里行间我们可以看出它用于表示有效的指针转换。它需要由程序员通过强制转换显式执行。

在 C 中,几乎任何对象指针都可以转换为另一个对象指针转换。但是,如果您通过错误的类型取消引用这样的指针,会发生什么情况却完全不同。大多数情况下,这是定义不明确的行为。

在这种情况下有效的指针转换:

  • 指向与第一个成员的类型兼容的类型的指针。1) 2) 3)
  • 一个空指针。1) 2)
  • 指向字符类型的指针。2)
  • 指向另一种结构类型的指针,其中两个结构都是 a 的一部分union并共享兼容类型的公共初始成员。4)

可选地,上述任何一种情况下的指针都可以是类型限定的。除非第一个成员是限定类型,在这种情况下,指针需要共享该类型的所有限定符。1) 3)

1)简单赋值规则 6.5.16.1。
2)关于指针转换的规则(6.3.2.3)。
3)兼容类型限定符的规则(6.7.3)。
4)共同初始序列规则(6.5.2.3)。

常见的初始序列一是一个奇怪的规则,它显然得到了较差的编译器支持,但它符合“严格别名”。

于 2021-03-22T14:18:24.860 回答