4

i was wondering whether union variable will be initialized like a structure variable or not...

#include<stdio.h>
int main(void)
{
 struct a
 {
 int i;
 char c;
 };
struct a ob={4};
printf("%d",ob.c);

}
the above code gives 0 as output..
so when i is intialized c also gets intialized..
in the below code...if the union member integer also gets intialized with the character array this snippet would give the output 515...
(i verified it by allocating memory for the union variable using malloc..it works fine.)

#include<stdio.h>
int main(void)
{
union a
{
int i;
char c[2];
 };
 union a ob;
 ob.ch[0]=3;
 ob.ch[1]=2;
 printf("%d",ob.i);
 return 0;
}

but without allocating memory whether it could intialize the int i or not..(the hex value of int i in this code is set to 0x990203).
i think that 99 is the result that shows that the higher bits are not intialized..
am i correct?..

jruizaranguren
  • 12,679
  • 7
  • 55
  • 73
cdummy
  • 455
  • 1
  • 4
  • 14
  • Reading from the field of the union to which you did not write is undefined behavior. You *could* see arbitrary data there, it worth nothing that your particular compiler does it one way or the other. – Sergey Kalinichenko Mar 22 '12 at 14:51
  • 2
    @dasblinkenlight: reading a member you did not write to is defined behaviour -- however, if that member is represented by bytes which did not partake in the last store (ie if the accessed member is of greater size than the member used in the last store), the behaviour is unspecified; see http://stackoverflow.com/a/8513748/48015 for details – Christoph Mar 22 '12 at 14:54
  • You may be right, have a look at the assembly output from your compiler to make sure. – Gowtham Mar 22 '12 at 14:54
  • could you comment about using malloc leaves the value of int to 515.. – cdummy Mar 22 '12 at 15:05

3 Answers3

2

Reading from a member of the union other than the one most recently written to outside the "byte footprint" of the member to which you have most recently written leads to undefined unspecified behavior. You should not be reading i until after you have written to it: Whatever you see there is non-portable junk.

EDIT 1 Edited in response to Cristoph's comment.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 3
    this is a common misconception - reading from a union member you haven't written to last is only illegal in C++; however, the value of a member is **unspecified** if the last store happened to a *smaller* one – Christoph Mar 22 '12 at 15:00
  • Yes, it is only undefined behavior if the contents of the object when interpreted as the type that you are accessing it is a trap representation. First, such trap representations are rare nowadays, and second you'd really have bad luck to see it. – Jens Gustedt Mar 22 '12 at 15:04
  • @Christoph Thanks for the correction! I've been out of the "pure C" world long enough to start thinking that C is a subset of C++ :) – Sergey Kalinichenko Mar 22 '12 at 15:08
1

i think that 99 is the result that shows that the higher bits are not intialized.. am i correct?..

Correct because you only assign to two bytes explicitly in your second example, so two bytes of the integer remain uninitialized. In the first example you assign 4 to i, which is an integer and shares a byte with c. However, If both union members are of same type, then assuming that both will be initialized is correct. Also, the space allocated for a union is the space taken by its largest member so assuming some of the bytes of i will change when you assign to c[x] would not be wrong.

The different values you may see for uninitialized bytes with different initialization methods, in different scopes and contexts are irrelevant, case specific and not defined. However, I cannot comment on 515 as it is not clear to me how you get that value.

perreal
  • 94,503
  • 21
  • 155
  • 181
1

Your assignment through the char could lead to undefined behavior if the new value happens to be a trap representation (rare) for the type int.

Your example with the union is not an initialization but only an assignment and thus it only changes exactly the bytes that you are accessing and the other stay with unspecific values. For unions it is always a good idea to do an initialization of the widest member something like

union a ob = { .i = 0 };

Thereby you can guarantee that all bytes of your object are initialized by 0.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • could you comment about using malloc leaves the value of int to 515. – cdummy Mar 22 '12 at 15:38
  • @cdummy, if you don't initialize the variable (on the stack or allocated with `malloc`) any value that happens to be in there is used for the `int` value. This is completely arbitrary. Only the two `char` you change directly have a value that you control. – Jens Gustedt Mar 22 '12 at 15:44
  • whether it is same for calloc – cdummy Mar 22 '12 at 15:49
  • With calloc you would be certain to get 515 (0x203, as you set the char array) because the upper bytes of the int would have been cleared by calloc. – William Morris Mar 22 '12 at 16:52