C标准:结构和联合说明符'的确切定义是什么;适当转换';?
N2479 C17..C2x工作草案-2020年2月5日ISO/IEC 9899:202x(E)(重点补充): 6.7.2.1结构和联合规范 17在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。经过适当转换的结构对象指针指向其初始成员(如果该成员是位字段,则指向其所在的单元),反之亦然。结构对象中可能有未命名的填充,但在其开头可能没有 18工会的规模足以容纳其最大的成员。在任何时候,联合对象中最多可以存储一个成员的值。经过适当转换的联合对象指针指向其每个成员(如果成员是位字段,则指向其所在的单元),反之亦然 问题:适当转换的C标准:结构和联合说明符'的确切定义是什么;适当转换';?,c,struct,language-lawyer,unions,c17,C,Struct,Language Lawyer,Unions,C17,N2479 C17..C2x工作草案-2020年2月5日ISO/IEC 9899:202x(E)(重点补充): 6.7.2.1结构和联合规范 17在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。经过适当转换的结构对象指针指向其初始成员(如果该成员是位字段,则指向其所在的单元),反之亦然。结构对象中可能有未命名的填充,但在其开头可能没有 18工会的规模足以容纳其最大的成员。在任何时候,联合对象中最多可以存储一个成员的值。经过适当转换的联合对象指针指向其每个成员(如果成员是位字
的确切定义是什么
额外说明:如果没有适当转换的的确切定义,那么C实施是否应记录其理解?例如(C/C++预处理器域),Microsoft将术语单个项
(C++,N4713)理解为单个、永久不可分割的预处理器令牌
(这会导致从gcc/clang/other移植代码时出现问题,而gcc/clang/other具有不同的理解),他们似乎没有记录他们对单个项目的理解
问题:适当转换的确切定义是什么
C标准没有给出“适当转换”的任何“精确定义”
我将其解释为指向“指向初始成员类型的指针”或“指向结构类型的指针”类型的任何转换序列,以便转换规范确保最终指针指向适当的地址。(例如,未通过可能不正确对齐的转换。)
额外:如果没有适当转换的确切定义,那么C实施文件应记录其理解吗
C标准不要求C实现记录其对“适当转换”的理解或解释。在此上下文中,“适当转换”指转换为适当兼容类型。例如:
#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;
}
#包括
结构mystruct{
双a;
int b;
};
int main()
{
结构mystruct s={2.5,4};
双*d=(双*)&s;
printf(“%f\n”,*d);//打印2.500000
返回0;
}
这里,struct mystruct
的第一个成员具有类型double
。因此,在这种情况下,“适当的转换”意味着可以通过显式转换将struct mystruct*
转换为double*
,它将指向a
成员。这不是一个具有特殊含义的术语
您正在处理从类型A到类型B的转换。类型A是指向结构类型的指针。未指定类型B,除非它必须适合用作指向初始成员的指针。因此,它必须是指针(因此我们只处理两种指针类型之间的转换),并且必须遵循严格的别名规则(目标类型可以是指向窄字符类型的指针,std::byte
、第一个成员的实际类型,或表示兼容的类型,例如仅在签名方面不同)
任何导致适当指针满足“适当转换”要求的指针转换。这不是一个正式术语,但在两行之间,我们可以看出它用于表示有效的指针转换。它需要由程序员通过强制转换显式执行
在C语言中,几乎任何对象指针都可以转换为另一个对象指针类型转换。但是,如果通过错误的类型取消引用这样的指针,情况就完全不同了。大多数情况下,这是定义不清的行为
这种情况下的有效指针转换:
- 指向与第一个成员的类型兼容的类型的指针。1)2)3)
- 空指针。1) (二)
- 指向字符类型的指针。2)
- 指向另一种结构类型的指针,其中两种结构都是
联合的一部分
,并共享兼容类型的公共初始成员。4)
上述任何情况下的指针都可以是类型限定的。除非第一个成员是限定类型,否则指针需要共享该类型的所有限定符。1) (三)
1) 简单作业规则6.5.16.1.
2) 有关指针转换的规则(6.3.2.3)。
3) 兼容类型限定符的规则(6.7.3)。
4) 共同初始顺序规则(6.5.2.3)
常见的初始序列1是一个奇怪的规则,它显然没有得到很好的编译器支持,但它符合“严格的别名”。其目的是,如果您有struct foo{int x;…}
,那么如果您将struct foo*
转换为int*
(比如通过强制转换)然后它指向相应的struct foo
的x
成员。是否有一个特定的代码示例,您不确定它是否符合定义?我认为您输入的关于C的90%问题可以回答为“C标准不是正式的数学/逻辑规范。”但是您也可以强制转换为常量double*
,例如。。。因此,“适当”并不是一成不变的。这并没有包括一个转换链,比如到void*
,然后到double*
,作为“适当转换”,但我希望包括这样的链,只要它们不会破坏某些东西。