This is a discussion on Can anyone explain this C program.. within the Computer Science & IT Engineering forums, part of the CE : Technical Discussions category; My mistake.. The code is this: void main() { int i; union { int a; struct { char b; char ...






My mistake.. The code is this:
ie, you should put the increment statement inside the for loop. Sorry..void main()
{
int i;
union
{
int a;
struct
{
char b;
char c;
}ch;
}num;
num.a=0;
for(i=0;i<5;i++)
{
num.ch.c++;
printf("%d\n",num.a);
}
}
Did you know??
Gravitation is not responsible for people falling in love.






Did you know??
Gravitation is not responsible for people falling in love.


My C programming skills are hazy, but i think a union cannot have a structure similar to the one you are using, something to do with it having only one value because of its memory structure.
i will confirm this later when i get time to go through my c programming books. For the time being do some digging on the memory structure of unions.
I propose that the reason is different implementations in compilers. Try printing characters as well as signed integer values, address the values differently, say as boolean strings, etc.
Also it isn't something you would do with a c compiler unless you were sure how it worked (my guess). C is intentionally not a safe language, it's been labeled the closest to the underlying machine as you get with compilation; you can write nice compilers (including C compilers) in cc and lex.
Last edited by skipper; 25th June 2009 at 11:37 AM.
To understand the logic behind the behavior, its good to have understanding of union. This is described below under "Understanding Union". For the user who know this or directly want to go through the rational refer "Rational Behind Behavior".
Understanding Union
Similar to structure, union is a way to create a user defined data type which can hold variables of different types and size. But the difference is the size of a structure is aggregate of size of all variables present in a structure (considering memory alignment) and every variable hold different memory location, whereas size of union is same as size of its widest member and a same memory location is shared by all members.
The variables of a union can also be accessed the way variables of a structure are accessed, i.e.,
<union name>.member
or
<union pointer name>->member
Consider below code:
The output of code is similar to:Code:#include "stdio.h" struct s { int i; char *p; }; union u { int i; char *p; }; int main() { struct s svar = { 0 }; union u uvar = { 0 }; char c = 0; svar.p = &c; uvar.p = &c; printf("Structure size: %d\n", sizeof(svar)); printf("Union size: %d\n", sizeof(uvar)); printf("i of structure: %d\n", svar.i); printf("i of Union: %d\n", uvar.i); printf("Address of c: %d\n", &c); return 0; }
Structure size: 8
Union size: 4
i of structure: 0
i of Union: 2293459
Address of c: 2293459
From the code and its output it can be noticed that:
1. The structure and union contain same variable but the size of structure and union is different. Structure occupies 8 bytes (aggregate of size of int and pointer to char). Whereas union occupies only 4 bytes (both int and pointer to char need 4 bytes and memory is shared between them).
2. We assigned the same address of variable 'c' to char pointers of structure and union. When we output the value of variable 'i' of structure, it is '0', i.e., the value assigned during initialization has not got modified because all variables of structure hold different memory location. Whereas when we output the value of variable 'i' of union, it is same as the address of variable 'c' assigned to variable 'p' of union. This is because the memory is shared between the variables of union.
Rational Behind Behavior
Let's discuss the actual problem statement now.
The code in the given problem statement is:
Here the union defined is:Code:void main() { union { int a; struct { char b; char c; }ch; }num; num.a=0; num.ch.c++; printf("%d",num.a); }
For the above union, the memory will be shared between the integer variable 'a' and structure variable 'ch'.Code:union { int a; struct { char b; char c; } ch; };
On a 32-bit machine, integer variable 'a' will take 4 bytes and the structure 'ch' will take 2 bytes. So the sharing of the memory will be as:
Consider the given case. When we assign '0' to variable 'a' the above shared memory will look like:Code:Variable a : MSB-> XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX <-LSB Variable ch: MSB-> XXXXXXXX XXXXXXXX <-LSB char c char b
And when we increment variable 'ch.c' by '1', the changes in shared memory will look like:Code:Variable a : MSB-> 00000000 00000000 00000000 00000000 <-LSB Variable ch: MSB-> 00000000 00000000 <-LSB char c char b
The decimal equivalent of binary value "00000000 00000000 00000001 00000000" is 256. Hence on incrementing 'ch.c' by one the value of 'a' got incremented by 256.Code:Variable a : MSB-> 00000000 00000000 00000001 00000000 <-LSB Variable ch: MSB-> 00000001 00000000 <-LSB char c char b
Consider one more increment in 'ch.c', the changes in shared memory will look like:
The decimal equivalent of binary value "00000000 00000000 00000010 00000000" is 512. Hence each increment in 'ch.c' increment the value of 'a' by 256.Code:Variable a : MSB-> 00000000 00000000 00000010 00000000 <-LSB Variable ch: MSB-> 00000010 00000000 <-LSB char c char b
Consider a case when we increment 'ch.b' instead of 'ch.c', the changes in shared memory will look like:
The decimal equivalent of binary value "00000000 00000000 00000000 00000001" is 1. Hence each increment in 'ch.b' increment the value of 'a' by 1.Code:Variable a : MSB-> 00000000 00000000 00000000 00000001 <-LSB Variable ch: MSB-> 00000000 00000001 <-LSB char c char b
The case can be extended to a union where the structure ch is having three character variables as:
For the above union the sharing of the memory will be as:Code:union { int a; struct { char b; char c; char d; } ch; };
Here if we initially assign '0' to variable 'a' and then increment variable 'ch.d' by 1, the memory will look like:Code:Variable a : MSB-> XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX <-LSB Variable ch: MSB-> XXXXXXXX XXXXXXXX XXXXXXXX <-LSB char d char c char b
The decimal equivalent of binary "00000000 00000001 00000000 00000000" is 65536, hence incrementing 'ch.d' by 1 will increment the value of 'a' by 65536.Code:Variable a : MSB-> 00000000 00000001 00000000 00000000 <-LSB Variable ch: MSB-> 00000001 00000000 00000000 <-LSB char d char c char b
Let me know if any item need more clarification.
-Pradeep
Last edited by pradeep_agrawal; 29th June 2009 at 01:36 PM.






Very good Explanation Pradeep.
Thanks
on 32-bit machine Integer takes 4 bytes , why does it take 4 ?
In the above code if we increment ch.b instead of ch.c are the values printed are 1 ,2 ,3 etc .
The data type 'int' was intended to always have size equal to the word size of the processor.
On a 16-bit machine the word size is 2byte and hence 'int' is of 2byte. Whereas on a 32-bit machine, the word size is of 4byte and hence 'int' is of 4byte. There are machines (e.g., 24bit DSP) where word size is 24-bit and hence size of 'int' is also 24bit.
Yes, as i states earlier in my explanation, when we increment ch.b instead of ch.c by 1, the value of 'a' also gets incremented by 1 instead of 256.
-Pradeep






Nice explanation Pradeep. Thanks very much..
However, I still have a doubt. Why does ch.b occupy the first position and ch.c the second? Is it because of the way we have defined them??
If the code had been,
then will the increments be 1 by 1 and not by 256??struct
{
char c;
char b;
}ch;
Did you know??
Gravitation is not responsible for people falling in love.






Yes SS , i guess its depends upon your declaration.