Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.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 - Fatal编程技术网

C 理解对象表示

C 理解对象表示,c,struct,language-lawyer,C,Struct,Language Lawyer,问题:如果我们有两个不兼容的结构或并集,但这两种类型的对象具有相同大小的对象表示,如果我将其中一种类型的某个对象的对象表示形式作为另一种类型“重新解释”,我会得到未定义/未指定/定义良好的行为吗。(我真的希望措辞不奇怪) 我的想法: 我提到结构或联合是因为N6.2.6.1(p6): 结构或联合对象的值决不是陷阱 我还发现,我们可以将对象的值复制到char数组6.2.6.1(p4): 该值可以复制到类型为无符号字符[n] (例如,通过memcpy);产生的字节集称为对象 值的表示 但是标准没有规定

问题:如果我们有两个不兼容的结构或并集,但这两种类型的对象具有相同大小的对象表示,如果我将其中一种类型的某个对象的对象表示形式作为另一种类型“重新解释”,我会得到未定义/未指定/定义良好的行为吗。(我真的希望措辞不奇怪)

我的想法:

我提到结构或联合是因为
N6.2.6.1(p6)

结构或联合对象的值决不是陷阱

我还发现,我们可以将对象的值复制到char数组
6.2.6.1(p4)

该值可以复制到类型为
无符号字符[n]
(例如,通过
memcpy
);产生的字节集称为对象 值的表示

但是标准没有规定我们可以将对象表示复制回去。因此,我认为将对象表示复制回具有相同大小表示的类型的对象(即使它不是陷阱)是非常必要的,但我不确定

示例:

结果可以用
struct test1\u t
int a之后的填充来解释

如果我们有两个不兼容的结构或并集,但是 这两种类型的对象表示大小相同 如果获取对象,则获取未定义/未指定/定义良好的行为 表示其中一种类型的某些对象并“重新解释”它 作为另一种类型

这个问题,特别是它包含了大量的相关信息和讨论,尽管它们侧重于不同的细节。特别是,

  • memcpy()
    本身就可以了,只要这两种类型的大小确实相同(在示例代码中似乎不太可能),并且
  • 因此,这部分取决于接收对象是否具有声明的类型。
    • 如果没有,则随后通过与源对象的有效类型不同的类型的左值访问它会生成UB
    • 如果确实如此(如示例中所示),那么访问结构本身是可以的,因为正如您所观察到的,结构类型没有陷阱表示
然而,在结构和工会的情况下,我们也必须考虑成员。它们的类型可能提供陷阱表示,如果提供,则
memcpy()
可能会导致一个或多个成员包含此类表示。读取当前包含陷阱表示的成员的值将生成UB

此外,即使假设示例中的两种结构类型具有相同的大小,它们的布局的相关细节也未指定。特别是,在您的示例代码中,如果两者都(1)两个结构的大小相同,(2)第二个
printf
调用打印代码注释所建议的结果,这将是令人惊讶的。(更正格式以正确匹配数据后;由于格式和变量之间不匹配,目前
printf
具有UB。)


因此,总体而言,您的示例代码并不严格符合要求。其行为的各个方面尚未明确,它可能(但不确定)表现出未定义的行为。

这在示例代码中似乎不太可能,但它们确实存在。我检查了它们的
sizeof
输出。在我的机器上等于16。我猜填充发生在
struct test1_t::a
@EOF中,正如参考答案中提到的,我们可以使用
memcpy
进行类型双关,在我的例子中,行为是定义良好的,因为
t1
声明了类型
struct test1_t
,这也是一种有效类型。
struct test1_t{
    int a;
    long b;
};

struct test2_t{
    int c;
    int d;
    int e;
    int f;
};


int main(){
      struct test1_t t1 = {.a = 100, .b = 2000};
      struct test2_t t2 = {.c = 1000, .d = 20000, .e = 300000, .f = 4000000};
      size_t size;
      if((size = sizeof(struct test1_t)) == sizeof(struct test2_t)){
          char repr[size];
          memcpy(&repr, &t2, size); // since value of structure or union
                                    // is never a trap why don't we treat
                                    // the representation as of some object
                                    // of type struct test_t1
          memcpy(&t1, &repr, size);
          printf("t1.a = %d\n", t1.a); //t1.a = 1000
          printf("t1.b = %d\n", t1.b); //t1.b = 300000
    }
}