C 在结构或联合体中使用衬垫是否安全?

C 在结构或联合体中使用衬垫是否安全?,c,struct,padding,C,Struct,Padding,考虑一下这段代码。填充物的存在是有保证的 static_assert(_Alignof(char) < _Alignof(double), "Flip!"); static_assert(sizeof(char) < sizeof(double), "Flop!"); struct S { char c[1]; double d; }; union U { char c[1]; double d; }; static_assert(sizeof(s

考虑一下这段代码。填充物的存在是有保证的

static_assert(_Alignof(char) < _Alignof(double), "Flip!");
static_assert(sizeof(char) < sizeof(double), "Flop!");

struct S {
    char c[1];
    double d;
};
union U {
    char c[1];
    double d;
};

static_assert(sizeof(struct S) == _Alignof(double) * sizeof(double), "Fudge!");
static_assert(sizeof(union U) == sizeof(double), "Futz!");

S s; U u;
s.c[1] = 0; // What?
u.c[1] = 0; // What?
静态断言(\u alingof(char)<\u alingof(double),“Flip!”);
静态断言(sizeof(char)

使用这些代码> StistaSypRe>/Cult>S,肯定在中间或结尾有填充。访问它们安全吗?

访问
memcpy()
memset()
或类似的整个结构是安全的,即使它包含填充位。但是,不能假设填充物保持其值

因此,访问填充位的唯一用途是,在某些情况下无需编写代码来避免访问它


对于像
memcmp()
这样的操作,访问填充位仍然是错误的,因为结果是不可预测的。

Afaik这是错误的,因为编译器可以尽可能在调试构建中对数组进行绑定检查。至于punnig类型,有一个问题是:AlligBing对重载数组没有太大影响,通常没有检测到,因为邻近字段,但是
c[1]
是一个错误,您无法可靠地访问填充。不能依赖在结构(并集)分配下复制的填充。从有字节的意义上来说,访问它们是“安全的”。你不能用它们做任何有意义或可靠的事情。如果要使用这样的字节,请明确说明:
struct S2{char c[1];short s;int i;double d;}
(在除32位Intel x86之外的大多数系统上,其大小将与问题中的
struct s
相同)。我相信您的第一个静态断言将在32位x86上启动。在
s
u
中访问
c[1]
是UB,而不管是否对齐或填充。为什么不声明一些占用“填充”字节的变量呢?那么你就不必问是否可以访问它们。