Combined memory share in C

Edit2: Can I polymorphism with Union? It seems to me that I can change the data structure based on my needs.

Edit: fix the code. Use the "." instead of "->". I want to ask how to make sure that the value is stored correctly when another data type (for example, int and char uses interchangebly? Since both have different memory sizes, the one that needs more memory will allocate memory space for sharing both types variables.

Suppose I have 2 structures:

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 types aType and bType will use the same memory. Since int has 3 bytes more (int is 4 bytes, and char is 1 byte), it will have 4 memory blocks. The first is the leftmost, and the last is the most correct. The time when I assign 'a' to the variable b from v1 will remain in the first block (left) of the memory block. The value 5 remains in the fourth memory block (at most).

Therefore, when it is printed out, it will produce the cost of garbage, right? If so, how to solve this problem? For this problem, which means that if I store "a" in b_type, then this value "a" must be in the shared memory, and not the previous integer value 5.

+4
source share
5 answers

Well, first of all, we need to know if you are using a Big Endian od Little Endian processor. Windows and Linux use the small endian format, which means that the value 0x00000005 is actually written as 05-00-00-00, as if you were writing it from right to left.
So, you put 5 in the part, which means that the first byte is 05, and all the rest is 00. Then you put "a" in the b part, which you overwrite 05 with the corresponding ascii value, that is, 0x61. When you look at the total number should be ... 97, that is, the value 0x61.

Union negotiation should start from the beginning, but the byte order is platform dependent. The Qhat you told shoul is correct under Big Endian architecture, like Sun Solaris or any Risc processor.

I'm wrong?

NTN

0
source

There is no right behavior. Setting a union through one element and extracting a value from another member causes undefined behavior. You can do useful things with this technique, but it depends on the hardware and the compiler. You will need to consider processor and memory matching requirements.

Back when I was doing almost all of my C programs, there were two (portable) methods using unions, which I relied quite heavily on.

Marked Union . This is great when you need a dynamically typed variable. You create a structure with two fields: a type discriminator and a union of all possible types.

 struct variant { enum { INT, CHAR, FLOAT } type; union value { int i; char c; float f; }; }; 

You just had to be very careful to set the type value correctly whenever you change the union value and retrieve only the value specified by the type.

General pointers . Since you can be sure that all pointers are the same size and presentation, you can create a union of types of pointers and know that you can set and retrieve values ​​interchangeably, regardless of type:

 typedef union { void *v; int* i; char* c; float* f; } ptr; 

This is especially useful for (de) serializing binary data:

 // serialize ptr *p; pv = ...; // set output buffer *p.c++ = 'a'; *p.i++ = 12345; *p.f++ = 3.14159; // deserialize ptr *p; pv = ...; // set input buffer char c = *p.c++; int i = *p.i++; float f = *p.f++; 

FYI:. You can make your example simpler. Structures are not needed. You will get the same behavior:

 int main() { union { int a; char b; } v1; v1.a = 5; v1.b = 'a'; } 
+7
source

The behavior you describe depends on the platform / system / compiler. For example, on Intel x86 processors, 5 is likely to be the first byte in int for the gcc compiler.

Interest in union comes from two main angles

  • share the same memory space to minimize the required memory allocation (in this case, the first byte [for example] can indicate the data type in the structure / union).
  • to analyze some data structure, without the need for castings and pointers. For example, combining between double and a char[8] on some platforms is an easy way to get the per-w980> / byte representation of a double structure.

If there is no use when using union , do not do this.

+1
source

The only way to fix this problem is to keep track of what data you saved. This is often done using a so-called tag member, for example:

 struct mystructA { int data; }; struct mystructB { char data; }; enum data_tag { TAG_STRUCT_A, TAG_STRUCT_B }; struct combined { enum data_tag tag; union { struct mystructA value_a; struct mystructA value_b; } data; }; 

Watching what data you insert, you can make sure that only then you will read the same field, thereby ensuring a meaningful result.

0
source

If you get access to the union with the same element to which you last tied to it, there will be no problems. When accessing a char-sized element for concatenation, the compiler will only return the bits of interest to you.

Edit: People mention tagged unions. Here is another style that the SDL uses for its event structure.

 enum union_tag { STRUCT_A, STRUCT_B }; typedef struct { enum union_tag tag; int a; } aType; typedef struct { enum union_tag tag; char b; } bType; typedef union{ enum union_tag tag; aType a_type; bType b_type; } ab; 

To access an element, you should do something like this:

 int result; switch(my_union.tag){ case STRUCT_A: result = my_union.a_type.a; break; case STRUCT_B: result = my_union.b_type.b; break; } 
0
source

Source: https://habr.com/ru/post/1335264/


All Articles