【问题标题】:Understanding object representation [duplicate]理解对象表示[重复]
【发布时间】:2019-03-08 14:50:08
【问题描述】:

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

我的想法:

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

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

另外我发现我们可以将一个对象的值复制到一个char数组6.2.6.1(p4)

可以将值复制到unsigned char [n] 类型的对象中 (例如,memcpy);结果的字节集称为对象 值的表示。

但标准并没有规定我们可以将对象表示复制回来。所以我认为将对象表示复制回具有相同大小表示的类型的对象(即使它不是陷阱)是UB,但我不确定......

示例:

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
    }
}

结果可以用struct test1_tint a;之后的填充来解释。

【问题讨论】:

  • @EOF 正如引用的答案中提到的,我们可以使用memcpy 进行类型双关语,在我的情况下,行为是明确定义的,因为t1 已声明类型struct test1_t,这是一个有效的也可以输入。

标签: c struct language-lawyer


【解决方案1】:

如果我们有两个不兼容的结构或联合,但对象 这两种类型都有 相同大小的对象表示 我会 如果我采取对象,得到未定义/未指定/明确定义的行为 表示其中一种类型的某些对象并“重新解释”它 作为另一种类型。

问题Can memcpy be used for type punning? 尤其是EOF's answer 包含大量相关信息和讨论,尽管它们侧重于不同的细节。特别是,

  • memcpy() 本身没问题,只要这两种类型确实具有相同的大小(在您的示例代码中似乎不太可能出现这种情况),并且
  • 从那里开始,它部分取决于接收对象是否具有声明的类型。
    • 如果不是,则随后通过与源对象的有效类型不同类型的左值访问它会产生 UB。
    • 如果确实如此,就像在您的示例中那样,那么访问结构本身就可以了,因为正如您所观察到的,结构类型没有陷阱表示。

但是,在结构和联合的情况下,我们还必须考虑成员。他们的类型可以提供陷阱表示,如果他们这样做,那么memcpy() 可能会导致一个或多个成员包含这种表示。读取当前包含陷阱表示的成员的值会产生 UB。

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

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

【讨论】:

  • 在您的示例代码中似乎不太可能出现这种情况,但确实如此。我检查了它们的sizeof 输出。在我的机器上等于 16。我猜填充发生在struct test1_t::a
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 1970-01-01
  • 2013-11-14
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2011-06-15
相关资源
最近更新 更多