Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C标准:结构和联合说明符'的确切定义是什么;适当转换';?_C_Struct_Language Lawyer_Unions_C17 - Fatal编程技术网

C标准:结构和联合说明符'的确切定义是什么;适当转换';?

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工会的规模足以容纳其最大的成员。在任何时候,联合对象中最多可以存储一个成员的值。经过适当转换的联合对象指针指向其每个成员(如果成员是位字

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*
,作为“适当转换”,但我希望包括这样的链,只要它们不会破坏某些东西。