Can anyone explain this C program..
Hi,
I was just trying something with C and I stumbled upon this little piece of code.
Each time I increment num.ch.c, the value of num.a increases by 256.
ie, if the value of num.ch.c is 3, the value of num.a would be 762.
Why is this so?
Note that, if I change the value of num.a, the value of num.ch.c does not change. It remains the same as num.a, which should be expected.
Please explain..
I was just trying something with C and I stumbled upon this little piece of code.
void main()The answer came out to be 256.
{
union
{
int a;
struct
{
char b;
char c;
}ch;
}num;
num.a=0;
num.ch.c++;
printf("%d",num.a);
}
Each time I increment num.ch.c, the value of num.a increases by 256.
ie, if the value of num.ch.c is 3, the value of num.a would be 762.
Why is this so?
Note that, if I change the value of num.a, the value of num.ch.c does not change. It remains the same as num.a, which should be expected.
Please explain..
Replies
-
skipperThe reason for the value sequence is because of the way the compiler assigns storage, the chars are stored backwards to how they get loaded into registers
The printf statement interprets the 16 bit value. -
ms_csOne question SS, How did you tell that, the value is incremented by 256?
Actually If you use union data type, the memory allocated based on members data type.And here memory allocated is 2 byte. First you have assigned 0 to a. Now this integer takes that 2 byte allocated memory. When you increment the member of struct , that will occupy those 2 byte memory. So again when you access integer, the same memory that 2 byte will be used, which doesnot have any value or it might have some garbage value. That;s why the result is 256.
Correct me If I am wrong -
ali_shakibaSalam = Hi;
I've also run the code; with some corrections to be build-able by gcc.
The result was 0 as I've commented the
num.ch.c++ line;
but after I un-comment it; the result was the same;
Dear skipper; I can not understand what you said;
The reason for the value sequence is because of the way the compiler assigns storage, the chars are stored backwards to how they get loaded into registers
Is it a standard? if yes, would you mind setting a reference point for it.
The printf statement interprets the 16 bit value.
Thanks in advance;
& With the hope of rising of Mahdi;
Ali -
silverscorpion
I couldn't get you?ms_csOne question SS, How did you tell that, the value is incremented by 256?
Actually If you use union data type, the memory allocated based on members data type.And here memory allocated is 2 byte. First you have assigned 0 to a. Now this integer takes that 2 byte allocated memory. When you increment the member of struct , that will occupy those 2 byte memory. So again when you access integer, the same memory that 2 byte will be used, which doesnot have any value or it might have some garbage value. That;s why the result is 256.
Correct me If I am wrong
How is the 'garbage value' increasing in steps of 256? -
silverscorpionOr, for your beter understanding, I'll reframe the question. Just insert a for loop before the print statement, and You'll see..
void main()
The answer came out to be,
{
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);
}
}
256
Can you understand my question now?
512
768
1024
1280 -
ms_csYour question is clear now. I will check and tell...
-
ali_shakibaSalam = Hi,
Dear silverscorpion; can you explain the context in which you faced this portion of code? or you faced it while you where playing with the C language?
If I know the context in which you faced it; I might be able to give you a solution and letting this problem to be studied later on;
Thanks
&
with the hope of rising of Mahdi;
Ali -
skipperIt's because the ORDER is different for character strings than ints, in the machine the compiler implements.
So if you store the characters "XY" in a and b , they are read as an int like: "YX", except the printf interprets a decimal integer (signed). Try a second printf that prints two characters in octal, say, or hex. -
ms_cs
void main()
The result for this is,
{
int i;
union
{
int a;
struct
{
char b;
char c;
}ch;
}num;
num.a=0;
num.ch.c++;
for(i=0;i<5;i++)
printf("%d\n",num.a);
}
256
I didn't get the following
256
256
256
256
256
512
768
1024
1280 -
silverscorpionMy mistake.. The code is this:
void main()
ie, you should put the increment statement inside the for loop. Sorry..
{
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);
}
} -
silverscorpion
Hi,ali_shakibaSalam = Hi,
Dear silverscorpion; can you explain the context in which you faced this portion of code? or you faced it while you where playing with the C language?
If I know the context in which you faced it; I might be able to give you a solution and letting this problem to be studied later on;
Thanks
&
with the hope of rising of Mahdi;
Ali
I faced this problem while I was just playing with C. There's no particular situation, so there's no need for a solution, per se.
I just wanted to know why this happens.
And thank you!! 😀😀 -
MungutiMy 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. -
skipperI 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. -
pradeep_agrawalTo 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.,
.member
or
->member
Consider below 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; }
The output of code is similar to:
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:
void main() { union { int a; struct { char b; char c; }ch; }num; num.a=0; num.ch.c++; printf("%d",num.a); }
Here the union defined is:
union { int a; struct { char b; char c; } ch; };
For the above union, the memory will be shared between the integer variable 'a' and structure variable '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:
Variable a : MSB-> XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX <-LSB Variable ch: MSB-> XXXXXXXX XXXXXXXX <-LSB char c char b
Consider the given case. When we assign '0' to variable 'a' the above shared memory will look like:
Variable a : MSB-> 00000000 00000000 00000000 00000000 <-LSB Variable ch: MSB-> 00000000 00000000 <-LSB char c char b
And when we increment variable 'ch.c' by '1', the changes in shared memory will look like:
Variable a : MSB-> 00000000 00000000 00000001 00000000 <-LSB Variable ch: MSB-> 00000001 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.
Consider one more increment in 'ch.c', the changes in shared memory will look like:
Variable a : MSB-> 00000000 00000000 00000010 00000000 <-LSB Variable ch: MSB-> 00000010 00000000 <-LSB char c char b
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.
Consider a case when we increment 'ch.b' instead of 'ch.c', the changes in shared memory will look like:
Variable a : MSB-> 00000000 00000000 00000000 00000001 <-LSB Variable ch: MSB-> 00000000 00000001 <-LSB char c char b
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.
The case can be extended to a union where the structure ch is having three character variables as:
union { int a; struct { char b; char c; char d; } ch; };
For the above union the sharing of the memory will be as:
Variable a : MSB-> XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX <-LSB Variable ch: MSB-> XXXXXXXX XXXXXXXX XXXXXXXX <-LSB char d char c char b
Here if we initially assign '0' to variable 'a' and then increment variable 'ch.d' by 1, the memory will look like:
Variable a : MSB-> 00000000 00000001 00000000 00000000 <-LSB Variable ch: MSB-> 00000001 00000000 00000000 <-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.
Let me know if any item need more clarification.
-Pradeep -
Saandeep SreerambatlaVery 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 . -
pradeep_agrawal
The data type 'int' was intended to always have size equal to the word size of the processor.English-Scaredon 32-bit machine Integer takes 4 bytes , why does it take 4 ?
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.English-ScaredIn the above code if we increment ch.b instead of ch.c are the values printed are 1 ,2 ,3 etc .
-Pradeep -
silverscorpionNice 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,
struct
then will the increments be 1 by 1 and not by 256??
{
char c;
char b;
}ch; -
Saandeep SreerambatlaYes SS , i guess its depends upon your declaration.
-
pradeep_agrawal
Yes it is because of the way you have defined the structure.silverscorpionWhy does ch.b occupy the first position and ch.c the second? Is it because of the way we have defined them??
If you declare ch.c first and ch.b later, then incrementing ch.c by 1 will increment 'a' by 1 and incrementing ch.b by 1 will increment 'a' by 256.
-Pradeep
You are reading an archived discussion.
Related Posts
Hey im sagar. Im doing engg from pune uni. Im in forth year now.
Please someone provide me new n latest topics that can be implemented with java n jsp,...
hi,
i am student of electrical engineering final year.kindly give me some new as well as telecom oriented project proposals.i will be thankul to all.regards
waqas
hi,
i am a BE graduate in computer science. i have an aggregate of 55% please tell me if i can get a job for my aggregate?
CEans,
It's been quite some time since Microsoft launched its BING search engine to rival Google.
I personally like Bing and have already started using it for almost 30-40% of...
Most of you have had a job offer when you graduated. Or those who are studying, will have multiple rounds of campus interviews.
Working for a startup or MNC has...