Union value in C

Viewed 78

Can somebody explain to me what happens with br agument in union, after assigning str.a and str.b? We need to set that value before calling the function above? I tried to run the code in simulator https://pythontutor.com/render.html#mode=display which says that the value of br is 516 before calling the function. How is that possible?

 #include <stdio.h>
void f(short num, short* res){
 if (num){
 *res = *res * 10 + num%10;
 f(num / 10, res);
}}


typedef union {
 short br;
 struct {
 char a, b;
 } str;
} un;

void main() {
 short res = 0; un x;
 x.str.a = 4; x.str.b = 2;
 f(x.br, &res); x.br = res;
 printf("%d %d %d\n", x.br, x.str.a, x.str.b);}
3 Answers

Assuming that char is one byte and short is two bytes (the most common), then it's really simple.

Begin by drawing out the members of the union on a piece of paper, one member next to the other. Something like this:

 br      str
+---+   +---+
|   |   |   | a
+---+   +---+
|   |   |   | b
+---+   +---+

Now we do the assignments:

x.str.a = 4;
x.str.b = 2;

And write the results in the drawing:

 br      str
+---+   +---+
| 4 |   | 4 | a
+---+   +---+
| 2 |   | 2 | b
+---+   +---+

Assuming little endianness like on a normal x86 or x86-64 system, then the value of br will be 0x0204 which is 516 in decimal.

So that's where the value 516 is coming from.

The value of the short will depend on the computer's endianess. On a little endian machine, a will correspond to the least significant byte and b to the most significant. Thus when those two bytes are converted to a short, you get the number 0x0204 = 516 decimal.

As a side note, it is a bad idea to use short and char since those may be signed and negative. Use uint16_t and uint8_t instead, whenever dealing with binary arithmetic.

If you put some effort into your debugging you would see what is going on:

void f(short num, short* res)
{
    if (num)
    {
        *res = *res * 10 + num%10;
        f(num / 10, res);
    }
}


typedef union 
{
    short br;
    struct 
    {
        char a, b;
    };
} un;

int main(void) 
{
    short res = 0; un x;
    x.a = 4; x.b = 2;
    printf("Before br=0x%04x (%d) a=0x%02x b=0x%02x res = %d 0x%x\n", x.br, x.br, x.a, x.b, res, res);
    f(x.br, &res); x.br = res;
    printf("After  br=0x%04x a=0x%02x b=0x%02x res = %d 0x%x\n", x.br, x.a, x.b, res, res);
}

result:

efore br=0x0204 (516) a=0x04 b=0x02 res = 0 0x0
After  br=0x0267 a=0x67 b=0x02 res = 615 0x267

Do your br was 516 and it was reversed by the f function becoming 615 which is 0x0276. It contains of two bytes 0x02 and 0x67.

Your computer is little-endian so the first byte is 0x67 and the second one is 0x02 because this system stores the least significant byte first.

Related