1
 union Data {
   int i;
   char s[20];
   } data;

int main(){
   printf( "%lu\n", sizeof( data ) );
   for( int i = 0; i < 20; ++i ) {
     data.s[i] = 0;
   }
   data.i = 0;
   strcpy( data.s, "Hello World!");
   if( data.i ) {
       strcpy( data.s, "Farewell!");
   }
   printf( "%s\n", data.s ); 

Why does it respond with "Farewell"? I would expect if( data.i ) to evaluate as False, but somehow it is evaluated as True.

hat
  • 781
  • 2
  • 14
  • 25
tgtrmr
  • 159
  • 9
  • 6
    `data.i` shares memory with `data.s`. You cleared `data.i`, but then subsequently filled `data.s` with non-zero values, so `data.i` is no longer zero. – Christian Gibbons Jul 23 '18 at 15:05
  • use a `struct` instead of an `union` – Jean-François Fabre Jul 23 '18 at 15:05
  • Curious: Why did code use `"%ld"` with `sizeof( )`? – chux - Reinstate Monica Jul 23 '18 at 15:15
  • To be mean: Because the compiler developer didn't make it say "Ha, ha,ha, now you die!". Accessing a member of a union that isn't the one last written (unless they have a common prefix) is undefined behavior. Anything can happen. Usually you simply get the bit pattern stored in the union interpreted as the other type as in your case. – Goswin von Brederlow Jul 23 '18 at 15:15
  • 1
    @GoswinvonBrederlow "Accessing a member of a union that isn't the one last written" sounds like a C++ thing. Confident that applies to C as in this post? – chux - Reinstate Monica Jul 23 '18 at 15:17
  • 1
    @chux You are correct, that is a C++ thing. It is legal, though perhaps ambiguously worded, in the C99 standard. The C11 standard fixed this and added in a footnote clarifying its legality. In the committee draft, it can be found in Section 6.5.2.3 footnote 95. – Christian Gibbons Jul 23 '18 at 15:26

1 Answers1

6

Unlike a struct, all fields in a union overlap each other in memory. So if you change one field, it affects all the others.

If you want the fields to be distinct from each other, declare a struct instead:

struct Data {
   int i;
   char s[20];
} data;
dbush
  • 205,898
  • 23
  • 218
  • 273