Jon*_*rdy 3 c struct casting undefined-behavior unions
我有一个union包含各种兼容struct成员:
enum Type { T1, T2, … };
struct S1 { enum Type type; … };
struct S2 { enum Type type; … };
…
union U {
enum Type type;
struct S1 as_s1;
struct S2 as_s2;
…
};
Run Code Online (Sandbox Code Playgroud)
type这些结构体的字段被视为不可变的,只type访问当前对应的联合的字段。据我所知,铸造union U *到struct S1 *,只要被定义type不变的坚持,而是相反也是如此?
struct S1 *s1 = malloc (sizeof (struct S1));
union U *u = (union U *)s1;
Run Code Online (Sandbox Code Playgroud)
也就是说,仅分配sizeof (struct S1)字节并将结果强制转换为安全union U *吗?我想避免分配sizeof (union U)字节,在我的情况下可能会大得多。
演员表本身不太可能成为问题。只要结构和联合类型具有相同的对齐要求,它们就被允许。此外,在这种情况下,标准要求如果将值转换回原始类型,则结果应与原始指针相等,因此不会丢失数据。
问题是当您访问指向的对象时会发生什么,就好像它是union U. 您可以通过这种方式做的某些事情可能会很好,但其他事情肯定是不安全的。具体你问
也就是说,仅分配 sizeof (struct S1) 字节并将结果转换为联合 U * 是否安全?
不,这不安全。该标准规定:
当值存储在结构或联合类型的对象中时,包括在成员对象中,对应于任何填充字节的对象表示的字节采用未指定的值。[...]
当值存储在联合类型对象的成员中时,不对应于该成员但对应于其他成员的对象表示的字节采用未指定的值。
(C2011, 6.2.6/6-7)
如果您触发这些规定之一,尤其是后者,并且分配的空间没有联合表示的那么大,那么程序就会表现出未定义的行为。您可能可以避免这样做的程序操作,但是在我的书中,对程序行为创建这种额外的约束不能被描述为“安全”。
我想避免分配 sizeof (union U) 字节,在我的情况下可能要大得多。
既然您显然打算使用type联合成员来确定要使用的成员,那么这样做如何:
struct generic_s {
enum Type type;
void *contents;
};
struct generic_s s = { T1 };
s.contents = malloc(sizeof (struct S1));
Run Code Online (Sandbox Code Playgroud)
struct_generic直接传递类型的对象以避免额外的分配和释放:
do_something(s); // i.e. not do_something(&s)
Run Code Online (Sandbox Code Playgroud)
当然,您需要contents强制转换指针以取消引用它。另一方面,这只是围绕指针来识别指向类型的一些花哨的包装。相反,您可以不进行包装并显式传递类型信息。
| 归档时间: |
|
| 查看次数: |
1463 次 |
| 最近记录: |