Why does this code produce the output shown?
#include<stdio.h>
struct sample{
int x:1;
}a[5]={0,1,2,3,4};
int main(){
int i;
for(i=0;i<5;++i){
printf("%d ",a[i].x);
}
return 0;
}
The output when compiled and executed using OnlineGDB is:
0 -1 0 -1 0
int x:1
acts as a signed one-bit integer. Per C 2018 6.7.2 5, an implementation may treat bit-fields declared as int
as unsigned int
, but the C implementation you are using appears to treated it as signed.
Additionally, the C implementation uses two’s complement. In two’s complement, an n-bit integer has 1 sign bit and n−1 value bits. Since your integer is one bit, it has one sign bit and zero value bits. Per the specification of two’s complement (C 2018 6.2.6.2 2), the value of the sign bit is −2M, where M is the number of value bits. Since that is zero, the value of the sign bit is −20 = −1.
Thus, the bit-field has value 0 when the bit is zero and value −1 when the bit is one.1
During initialization with ={0,1,2,3,4};
, the first bit-field in the array is set to zero. However, the others overflow the values representable in the bit-field. Per C 2018 6.3.1.3 3, either an implementation-defined result is produced or an implementation-defined signal is raised. This C implementation appears to be producing the low bit of the source value as the value for the bit in the bit-field. This produces bits of 0, 1, 0, 1, and 0 in the five bit fields, representing values of 0, −1, 0, −1, and 0. Thus, when they are printed, the values 0, −1, 0, −1, and 0 result.
1 This may be seen as a natural consequence of how two’s complement normally works: With eight bits, the range is −128…127. With four bits, the range is −16…15. With fewer and fewer bits, the range is −8…7, −4…3, −2…1, and finally −1…0.
The designation 'int x:1' means it consider only one bit of x (2^0 bit) as a range of this integer. That explains why the output is 0 and 1. The negative value is due to 'int' normally reserve the last bit (2^31) to designate if the number is negative or not. your in x:1 has one bit and that bit also indicate it is a negative number.
If you try out 'unsigned x:1' it will output a positive number because the last bit of you 'x:int' doesn't designate a negative number.
Try this program with 'int x:2' and 'unsigned x:2' and you see an interesting behavior.
It clarify why the range of int and unsigned are so different despite the they have the same size of bits:
int -> -2,147,483,648 to 2,147,483,647
unsigned -> 0 to 4,294,967,295
Important to note the bit position used used by ':' to limit the range is up to implementation and may give you other results.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With