将结构指针转换为联合指针 [英] Casting structure pointer to union pointer

查看:119
本文介绍了将结构指针转换为联合指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个工会,其中包含各种兼容的 struct 成员:

I have a union containing various compatible struct members:

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

处理这些结构的 type 字段为不可变的,并且仅访问与当前 type 相对应的并集字段。我知道将 union U * 强制转换为 struct S1 * 是定义的,只要类型不变,但是反过来也成立吗?

The type field of these structures is treated as immutable, and only the field of the union corresponding to the current type is accessed. I am aware that casting union U * to struct S1 * is defined as long as the type invariant is upheld, but is the reverse also true?

struct S1 *s1 = malloc (sizeof (struct S1));
union U *u = (union U *)s1;

也就是说,仅分配 sizeof(结构S1)是否安全? / code>字节并将结果转换为 union U * ?我想避免分配 sizeof(union U)个字节,在我看来,这可能会更大。

That is, is it safe to allocate only sizeof (struct S1) bytes and cast the result to union U *? I would like to avoid allocating sizeof (union U) bytes, which in my case may be significantly larger.

推荐答案

强制转换本身不太可能成为问题。只要结构和联合类型具有相同的对齐要求,就可以使用它们。此外,在那种情况下,标准要求如果将值转换回原始类型,则结果应与原始指针进行比较,因此不会丢失任何数据。

The casts themselves are not likely to be a problem. They are permitted as long as the struct and union types have the same alignment requirement. Moreover, in that case the standard demands that if the value is converted back to the original type then the result shall compare equal to the original pointer, so no data is lost.

问题是当您访问所指向的对象时,好像它是一个联合U ,会发生什么。您可能以这种方式执行的某些操作可能会正常工作,但其他某些操作绝对是不安全的。具体来说,您问

The problem is what happens when you access the pointed-to object as if it were a union U. It is likely that some things you could do that way would work out fine, but others are definitely unsafe. Specifically, you ask


也就是说,仅分配sizeof(结构S1)字节并将结果转换为并集U *是否安全?

That is, is it safe to allocate only sizeof (struct S1) bytes and cast the result to union U *?

不,这不安全。该标准指定:

No, it is not safe. The standard specifies:


当值存储在结构或联合类型的对象(包括成员对象)中时,与任何填充字节相对应的对象表示形式均采用未指定的值。 [...]

When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values. [...]

当值存储在联合类型的对象的成员中时,该对象表示形式的字节与该成员不对应,但可以对应于其他成员采用未指定的值。

When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.

(C2011,6.2.6 / 6-7)

(C2011, 6.2.6/6-7)

如果您触发其中一个规定,尤其是后者,并且分配的空间不如联合的表示那么大,则程序表现出未定义的行为。可以避免这样做的程序动作,但是在我的书中,不能将对程序行为的这种额外约束描述为安全。

If you trigger one of those provisions, especially the latter, and the allocated space is not as big as the union's representation, then the program exhibits undefined behavior. It is possible that you could avoid program actions that do so, but creating such extra constraints on program behavior cannot be characterized as "safe" in my book.


我想避免分配sizeof(联合U)字节,在我看来,这可能会更大。

I would like to avoid allocating sizeof (union U) bytes, which in my case may be significantly larger.

您显然打算使用工会的 type 成员来标识要使用的成员,如何执行此操作:

Since you apparently intend to use the type member of the union to identify which member to use, how about doing this:

struct generic_s {
    enum Type type;
    void *contents;
};

struct generic_s s = { T1 };
s.contents = malloc(sizeof (struct S1));

直接传递 struct_generic 类型的对象避免额外的分配和取消分配:

Pass around objects of type struct_generic directly to avoid extra allocations and deallocations:

do_something(s);  // i.e. not do_something(&s)

您需要投放 contents 指针可以取消引用它。另一方面,所有这些只是花哨的环绕指针来标识指向类型。相反,您可以不用包装而直接传递类型信息。

You would need to cast the contents pointer to dereference it, of course. On the other hand, that's all just a bit of fancy wrapping around the pointer to identify the pointed-to type. You could instead do without the wrapping and pass around the type information explicitly.

这篇关于将结构指针转换为联合指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆