C 中的联合内存共享
Edit2:我可以用 Union 进行多态吗?在我看来,我可以根据我的需要更改数据结构。
编辑:修复代码。使用 ”。”而不是“->”。我想问的是,当存在不同的数据类型时(例如 int 和 char 互换使用)如何确保值正确存储?由于两者的内存大小不同,需要更大内存空间的将为两者分配内存空间 据
假设我有 2 个结构体:
typedef struct a{
int a;
}aType;
typedef struct b{
char b;
}bType;
typedef union{
aType a_type;
bType b_type;
}ab;
int main(void){
ab v1;
v1.a_type.a = 5;
v1.b_type.b = 'a'
}
我所知,aType 和 bType 将共享相同的内存,因为 int 多了 3 个字节(int 是 4 个字节,char 是 1 个字节),因此它有4 个内存块。第一个是最左边的,最后一个是最右边的。当我将“a”分配给 v1 的变量 b 时,它将保留在内存块的第一个块(最左边)中。值5仍然保留在第四块内存中(最右边),
因此,当打印出来时,它会产生垃圾值,不是吗?如果是这样,如何解决这个问题?我将“a”存储到b_type中,共享内存必须确保只有该值“a”,而不是之前的整数值5。
Edit2: Can I do polymorphism with Union? It seems to me that I can change the data structure based on my need.
Edit: Fix the code. Use "." instead of "->". What I want to ask is, how to make sure the value is stored correctly when there's different data type (like int and char use interchangebly? Since both has different memory size, the one which needs bigger memory space would be allocate memory space for both types of variables to share.
Suppose I have 2 structs:
typedef struct a{
int a;
}aType;
typedef struct b{
char b;
}bType;
typedef union{
aType a_type;
bType b_type;
}ab;
int main(void){
ab v1;
v1.a_type.a = 5;
v1.b_type.b = 'a'
}
As far as I know, both aType and bType will share the same memory. Since int has 3 bytes greater (int is 4 bytes, and char is 1 byte), it will have 4 memory blocks. The first one is the left most and the last one is the right most. The time I assign 'a' to variable b of v1, it will stay in the first block (the left most) of memory block. The value 5 still remains in the fourth block of memory (the right most).
Therefore, when prints it out, it will produce garbage value, won't it? If so, how to fix this problem? By this problem, which means if I store 'a' into b_type, the share memory must be sure to have that value 'a' only, not the previous integer value 5.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
解决此问题的唯一方法是跟踪您存储的数据。这通常是使用所谓的标签成员来完成的,如下所示:
通过仔细跟踪您输入的数据,您可以确保稍后只读取相同的字段,从而确保您获得有意义的结果。
The only way to fix this problem is by keeping track of what data you have stored. This is often done using a so-called tag member, like so:
By keeping careful track of what data you put in, you can make sure only to read that same field later, thus ensuring you get a meaningful result.
如果您通过上次分配给它的相同元素访问联合体,则不会有问题。通过访问联合的 char 大小的元素,编译器确保只返回您感兴趣的位。
编辑:人们提到了标记的联合。这是 SDL 用于其事件结构的另一种风格。
要访问一个元素,你可以这样做:
If you access the union by the same element you last assigned to it with, there will be no problem. By accessing the char sized element of the union, the compiler makes sure to only return the bits you are interested in.
Edit: People were mentioning tagged unions. Here is another style of that, which SDL uses for their event struct.
To access an element you would do something like this:
没有正确的行为。通过一个成员设置联合并从另一成员检索值会导致未定义的行为。您可以使用此技术做一些有用的事情,但它非常依赖于硬件和编译器。您将需要考虑处理器字节顺序和内存对齐要求。
当我几乎用 C 语言进行所有编程时,我非常依赖两种使用联合的(可移植)技术。
带标签的联合。当您需要动态类型变量时,这非常有用。您设置一个具有两个字段的结构:类型判别式和所有可能类型的联合。
每当更改联合值时,您都必须非常小心地正确设置类型值,并仅检索类型指定的值。
通用指针。由于您可以非常确定所有指针都具有相同的大小和表示形式,因此您可以创建指针类型的联合,并且知道您可以互换地设置和检索值,而无需考虑类型:
这对于(反)序列化二进制数据特别有用:
仅供参考:您可以使示例更简单。这些结构是不必要的。你会得到同样的行为:
There is no right behavior. Setting a union via one member and retrieving a value from a different member causes undefined behavior. You can do useful things with this technique, but it is very hardware and compiler dependent. You will need to consider processor endianness and memory alignment requirements.
Back when I did almost all my programming in C, there were two (portable) techniques using unions that I relied on pretty heavily.
A tagged union. This is great when you need a dynamically typed variable. You set up a struct with two fields: a type discriminant and a union of all possible types.
You just had to be very careful to set the type value correctly whenever you changed the union's value and to retrieve only the value specified by the type.
Generic pointers. Since you can be pretty sure that all pointers have the same size and representation, you can create a union of pointer types and know that you can set and retrieve values interchangeably without regard to type:
This is especially useful for (de)serializing binary data:
FYI: You can make your example simpler. The structs are unnecessary. You'll get the same behavior with this:
您描述的行为取决于平台/系统/编译器。例如,在 Intel x86 处理器上,
5
可能是gcc
编译器的int
中的第一个字节。联合的兴趣来自于两个主要角度
double
和char[8]
之间的并集是获取 double 的每个字符/字节视图的简单方法 结构。如果使用
union
没有任何好处,请不要这样做。The behavior you describe is platform/system/compiler dependent. On Intel x86 processors, for instance, the
5
is likely to be the first byte in theint
for thegcc
compiler.The
union
interest comes from two main anglesdouble
and achar[8]
on some platforms is an easy way to get a per-char/byte view of thedouble
structure.If there is no benefit in using a
union
, don't do it.好吧,首先我们应该知道您是否使用的是 Big Endian 或 Little Endian 处理器。
窗口& Linux 使用小端格式,这意味着值 0x00000005 实际上写为 05-00-00-00,就像从右向左写一样。
因此,首先将 5 放入一个部分中,这意味着第一个字节是 05,其他字节都是 00。
将 'a' 放入 b 部分,然后用相应的 ascii 值覆盖 05,这意味着 0x61。
当你看一下结果数字应该是…97,那就是0x61的值。
联合的对齐应从头开始,但字节顺序取决于平台。
您所说的问题在 Big Endian 架构下应该正确,如 Sun Solaris 或任何 Risc 处理器。
我错了吗?
华泰
Well, first of all we should know if you're using a Big Endian od Little Endian processor.
Windows & Linux uses little endian format that means that the value 0x00000005 is actually written as 05-00-00-00, as if you write it right to left.
So, firs you put 5 into a part that means that the first byte is 05 and all the others are 00.
Than you place 'a' into b part you overwrite 05 with corresponding ascii value, that means 0x61.
When you look at the resulting number should be ... 97, that is the value of 0x61.
Alignment of union should start at the beginning, but byte order is platform dependent.
Qhat you told shoul de correct under Big Endian architecture, as Sun Solaris or any Risc processor.
Am I wrong?
HTH