【问题标题】:C: casting to structure with different sizeC:铸造成不同尺寸的结构
【发布时间】:2017-04-03 08:54:08
【问题描述】:

快速简单的问题; 这样做

typedef struct {int a; int b;} S1;
typedef struct {int a;} S2;
((S2*)(POINTER_TO_AN_S1))->a=1;

总是返回(并分配)结构的成员 a?还是未定义的行为?

【问题讨论】:

  • 语言标签在涉及代码时很重要(即几乎总是在 Stack Overflow 上)。

标签: c struct casting variable-assignment undefined-behavior


【解决方案1】:

在符合标准的编译器中,如果两种结构类型都出现在联合类型的完整定义中,在访问该结构时可见,并且如果指针的目标恰好是该联合类型的实例,则行为将是定义。请注意,该标准不要求编译器有任何方式知道指针的目标实际上是该联合类型的对象——只是完整联合类型的声明是可见的。

但是请注意,这里 gcc 不遵守标准,除非使用了 -fno-strict-aliasing 标志。即使在完整的联合类型可见的情况下,并且编译器可以看到它实际上正在处理联合类型的对象,gcc 也会忽略别名。例如,给定:

struct s1 {int x;};
struct s2 {int x;};
union u { struct s1 s1; struct s2 s2;};

int read_s1_x(struct s1 *p) { return p->x; }
int read_s2_x(struct s2 *p) { return p->x; }
int write_s1_x(struct s1 *p, int value) { p->x = value; }
int write_s2_x(struct s2 *p, int value) { p->x = value; }

int test(union u *u1, union u *u2)
{
  write_s2_x(&u2->s2, 0);
  if (!read_s1_x(&u1->s1))
    write_s2_x(&u2->s2, 1);
  return read_s1_x(&u1->s1);
}

编译器将决定它不需要重新读取 u1->s1.x 在它写入 u2->s2.x 之后,即使是完整的联合类型 是可见的,即使编译器可以看到 u1 和 u2 都是 指向联合类型对象的指针。我不太确定是什么 gcc 的作者认为地址操作符应该意味着什么时候 如果结果指针甚至不能用于联合类型,则应用于联合类型 立即访问该成员类型的对象。

【讨论】:

    猜你喜欢
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    • 2013-05-31
    • 2011-05-28
    相关资源
    最近更新 更多