crypto.bi

C Programming: Reading from inactive union members

Unions are an interesting construct that you’re likely to find in C programs.

A union looks similar to a struct on the outside, but it has a special quality that it can only hold one of its declared values at a time.

So, what happens if we write to one member and then read from inactive fields? Let’s try and see!

#include <stdio.h>

union s {
    int a;
    float b;
    double c;
    unsigned long d;
};

void print_union(union s *mu){
    printf("a %d\n", mu->a);
    printf("b %f\n", mu->b);
    printf("c %f\n", mu->c);
    printf("d %lu\n", mu->d);
    printf("-----------\n");
}

int main(int argc, char **argv) {

    union s mu;

    mu.a = -9;
    print_union(&mu);

    mu.b = 11.3;
    print_union(&mu);

    mu.c = 137.101754;
    print_union(&mu);

    mu.d = 7267383982;
    print_union(&mu);

    return 0;
}

Running this on the following system…

Linux trainwreck-PC 5.4.0-47-generic #51-Ubuntu SMP Fri Sep 4 19:50:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0

… yields this:

a -9
b -nan
c 0.000000
d 140737488355319
-----------
a 1093979341
b 11.300000
c 0.000000
d 140734287367373
-----------
a -1852127337
b -0.000000
c 137.101754
d 4639027855691007895
-----------
a -1322550610
b -0.000000
c 0.000000
d 7267383982
-----------

As you can see, each time the print_union subroutine is called, only the most recently assigned member displays a correct value.

So, where do those other values come from? The C standard doesn’t say, so it’s undefined behavior.

It’s likely the union memory region being erroneously interpreted as some other type. If you run the above program multiple times, some values may vary while others don’t, so it’s not just memory noise. For instance, -9 converted to unsigned long does not equal the value displayed by print_union on the first case where we have a = -9.

Using union‘s this way voids your C warranty, so don’t do it. But in case you’re curious, this little program illustrates what you should expect from reading inactive C union members.

Links

Union entry at CPPReference

Accessing inactive union member and undefined behavior?

C++ Union Member Access And Undefined Behaviour

#CryptoPB

Crypto.BI CryptoPB Presents