Using bit with int in structure - c

#include<stdio.h>
struct a
{
int a:4;
};
main(){
struct a aa;
aa.a=9;
printf("a=%d\n",aa.a);
return 0;
}
Here the output is -7. Why is it so?
what does exactly int a:4 does ? please explain

Since it's two's complement, the highest order bit is used for the sign. By writing a:4 you're saying to only allocate 4 bits of memory, which leaves 3 bits left over for the actual number. So our effective range is [-8,7]. Since all 1's is -1, there's an extra number on the negative side. For more of an explanation on this, see the above link.
9, in (unsigned) binary is: 1001. When you put this into a (signed), you get that a is negative, due to the initial 1, and since the following numbers are 001, we add 1 to the max negative number, thereby giving us -7.
If you want to store the number 9 in only 4 bits, you need to use an unsigned int, which would give you a range of [0, 15].
EDIT:
In case anyone is struggling with figuring out how 1001 signed gives us -7, consider the following:
Since 1111 is -1, let some variable value = -1.
To figure out the values of a negative (signed) int num, let us denote xi in num:
xi : {0,1 at position i, where i=0 is the least significant bit)},
Then, for every xi = 0, subtract 2i from value.
Example:
1001:
value = -1 - 21 - 22 = -7

Your field is a 4 bit signed integer. For signed integers the upper bit is a sign bit, which means that you only have 3 bits for the actual number. The range of numbers you can store in the field are -8 to 7 (assuming 2's compliment storage).
The bit pattern for 9 is 1001, which has the 4th bit set, meaning it is interpreted as a negative number, which is why it is printing out as a -7. If you would have expected a -1, you need to read up on 2's compliment.
If you want to be able to store 9 in the field, make a an unsigned int

You only reserved 4 bits for the field, one bit is used for the sign, so only 3 bits remain for positive values. Thus you can only store values up to 7.

you have to use unsigned indeed int :
#include<stdio.h>
struct a
{
unsigned a:4; // <-- unsigned indeed int, then work good
};
main(){
struct a aa;
aa.a=9;
printf("a=%d\n",aa.a);
return 0;
}
output :
a=9

Related

Using an unsigned int in a do-while loop

I'm new to coding in c and I've been trying to wrap my head around unsigned integers. This is the code I have:
#include <stdio.h>
int main(void)
{
unsigned int hours;
do
{
printf("Number of hours you spend sleeping a day: ");
scanf(" %u", &hours);
}
while(hours < 0);
printf("\nYour number is %u", hours);
}
However, when I run the code and use (-1) it does not ask the question again like it should and prints out (Your number is 4294967295) instead. If I change unsigned int to a normal int, the code works fine. Is there a way I can change my code to make the unsigned int work?
Appreciate any help!
Is there a way I can change my code to make the unsigned int work?
Various approaches possible.
Read as int and then convert to unsigned.
Given "Number of hours you spend sleeping a day: " implies a small legitimate range about 0 to 24, read as int and convert.
int input;
do {
puts("Number of hours you spend sleeping a day:");
if (scanf("%d", &input) != 1) {
Handle_non_text_input(); // TBD code for non-numeric input like "abc"
}
} while (input < 0 || input > 24);
unsigned hours = input;
An unsigned int cannot hold negative numbers. It is useful since it can store a full 32 bit number (twice as large as a regular int), but it cannot hold negative numbers So when you try to read your negative unsigned int, it is being read as a positive number. Although both int and unsigned int are 32 bit numbers, they will be interpreted much differently.
I would try the next test:
do:{
printf("enter valid input...")
scanf("new input...")
} while (hours > 24)
Why should it work?
An unsigned int in C is a binary number, with 32 bit. that means it's max value is 2^32 - 1.
Note that:
2^32 - 1 == 4294967295. That is no coincidence. Negative ints are usually represented using the "Two's complement" method.
A word about that method:
When I use a regular int, it's most significant bit is reserved for sign: 1 if negative, 0 if positive. A positive int than holds a 0 in it's most significant bit, and 1's and 0's on the remaining coordinates in the ordinary binary manner.
Negative ints, are represented differently:
Suppose K is a positive number, represented by N bits.
The number (-K) is represented using 1 in the most significant bit, and the POSITIVE NUMBER: (2^(N-1) - K) occupying the N-1 least significant bits.
Example:
Suppose N = 4, K = 7. Binary representation for 7 using 4 bit:
7 = 0111 (The most significant bit is reserved for sign, remember?)
-7 , on the other hand:
-7 = concat(1, 2^(4-1) - 7) == 1001
Another example:
1 = 0001, -1 = 1111.
Note that if we use 32 bits, -1 is 1...1 (altogether we have 32 1's). This is exactly the binary representation of the unsigned int 4294967295. When you use unsigned int, you instruct the compiler to refer to -1 as a positive number. This is where your unexpected "error" comes from.
Now - If you use the while(hours>24), you rule out most of the illegal input. I am not sure though if you rule out all illegal input. It might be possible to think of a negative number such that the compiler interpret it as a non-negative number in the range [0:24] when asked to ignore the sign, and refer to the most significant bit as 'just another bit'.

How to create a negative binary number using signed/unsigned in C?

My thoughts: if one declares an int it basically gets an unsigned int. So if I need a negative value I have to explicitly create a signed int.
I tried
int a = 0b10000101;
printf("%d", a); // i get 138 ,what i've expected
signed int b = 0b10000101; // here i expect -10, but i also get 138
printf("%d", b); // also tried %u
So am I wrong that an signed integer in binary is a negative value?
How can I create a negative value in binary format?
Edit Even if I use 16/32/64 bits I get the same result. unsigned/signed doest seems to make a difference without manually shifting the bits.
If numbers are represented as two's complement you just need to have the sign bit set to ensure that the number is negative. That's the MSB. If an int is 32 bits, then 0b11111111111111111111111111111111 is -1, and 0b10000000000000000000000000000000 is INT_MIN.
To adjust for the size int(8|16|64)_t, just change the number of bits. The sign bit is still the MSB.
Keep in mind that, depending on your target, int could be 2 or 4 bytes. This means that int a=0b10000101 is not nearly enough bits to set the sign bit.
If your int is 4 bytes, you need 0b10000000 0000000 0000000 00000000 (spaces added for clarity).
For example on a 32-bit target:
int b = 0b11111111111111111111111111111110;
printf("%d\n", b); // prints -2
because int a = 0b10000101 has only 8 bits, where you need 16 or 32. Try thi:
int a = 0b10000000000000000000000000000101
that should create negative number if your machine is 32bits. If this does not work try:
int a = 0b1000000000000101
there are other ways to produce negative numbers:
int a = 0b1 << 31 + 0b101
or if you have 16 bit system
int a = 0b1 << 15 + 0b101
or this one would work for both 32 or 16 bits
int a = ~0b0 * 0b101
or this is another one that would work on both if you want to get -5
int a = ~0b101 + 1
so 0b101 is 5 in binary, ~0b101 gives -6 so to get -5 you add 1
EDIT:
Since I now see that you have confusion of what signed and unsigned numbers are, I will try to explain it as simple as possible int
So when you have:
int a = 5;
is the same as:
signed int a = 5;
and both of them would be positive. Now it would be the same as:
unsigned int a = 5;
because 5 is positive number.
On the other hand if you have:
int a = -5;
this would be the same as
signed int a = -5;
but it would not be the same as following:
unsigned int a = -5;
the first 2 would be -5, the third one is not the same. In fact it would be the same if you entered 4294967291 because they are the same in binary form but the fact that you have unsigned in front means that compiler would store it the same way but treat it as positive value.
How to create a negative binary number using signed/unsigned in C?
Simply negate the constant of a positive value. To attempt to do so with many 1's
... 1110110 assumes a bit width for int. Better to be portable.
#include <stdio.h>
int main(void) {
#define NEGATIVE_BINARY_NUMBER (-0b1010)
printf("%d\n", NEGATIVE_BINARY_NUMBER);
}
Output
-10

Depiction of binary digit changes during promotion from signed to unsigned integers/what happens?

y is promoted to unsigned int and compared with x here.Does binary number comparison happen everytime? Then if(12 == -4) is done, why can't it promote LHS to unsigned and print "same"?(considering 12 = 1100, -4 = 1100)Please correct if I am wrong.
#include<stdio.h>
int main()
{
unsigned int x = -1;
int y = ~0;
if(x == y)//1.what happens if( y == x) is given?.O/P is "same" then also.
printf("same");//output is "same"
else
printf("not same");
printf("%d",x);//2.output is -1.Won't x lose it's sign when unsigned is given?My hunch is x should become +1 here.
getchar();
return 0;
}
Please also provide the binary number working for the above code and answers to 1. and 2. in the code comments.Thank you.
First check in your system for size of unsigned int.
in my machine: printf("%zu\n",sizeof(unsigned int));//4 byte
as we have 4 bytes to store an Uint data type, we can say
unsigned int x ;//
x:Range[0, Max_number_with_4byte]
Max_number_with_4byte: (2^32) - 1 = 0xFFFFFFFF
obviously x can hold only positive numbers because of unsigned.
but you give to x = -1;, suppose a circular behaviour, when we put back one step from 0, x reach to last point: Max_number_with_4byte.
and printing x to screen shows: 0xFFFFFFFF
see hex equivalent of x with printf("%x\n",(unsigned int )x);
and printf("%y\n",(unsigned int )y); to see equality of x,y.
consider y = ~0; we have 32 bits for y if ~ operator use in y all bits are changes to 1, in hex form we see FFFFFFFF. (we cant print binary numbers with printf and use equal hex representation)
you can see this online calculator how to convert -1 to 0xFFFFFFFF
Answer to your Question
y is not promoted to unsigned int. it is just changes its bits form 0 -> 1
Does binary number comparison happen every time?
Yes in every conditions for example in if(10 > 20) first both 10 and 20 converted to its correspondent binary numbers then compare.
if (12 == -4) see my above explanation.
-4 not equals to 1100 inside computer (your variable).
-4 = 0xFFFFFFFC see
An unsigned int =-1 should actually interpreted as the max unsigned int(4294967295); surely is not transformed into 1.

struct default values in c

I came across this problem in C using structs.I'm not sure of what is really happening here
Thanks
#include<stdio.h>
int main()
{
struct num1
{
int n1:2;
int n2:3;
int n3:4;
};
struct num1 num={3,4,5};
printf("%d %d %d\n",num.n1,num.n2,num.n3);
return 0;
}
The obtained output is
-1 -4 5
These are bit fields, the number after the : specifies how many bits are in that member.
int n1:2
means a signed integer with 2 bits. In two's complement notation, this allows for values from -2 to 1; in sign+magnitude notation it allows for -1 to 1. When you try to assign 3 to this member, you get overflow, which results in undefined behavior.
Similarly
int n2:3
means a signied integer with 3 bits, whose range is -4 to 3 in two's complement, -3 to 3 in sign+magnitude, so assigning 4 causes overflow.
int n3:4
has a range from -8 to 7 or -7 to 7, so assigning 5 fits into it, so there's no overflow.

Can you explain how int values are stored in bitfields in C, please?

#include <stdio.h>
struct marks{
int p:4;
int c:3;
unsigned int m:2;
};
void main()
{
struct marks s = {-15, 5, 3};
printf("%d %d %d\n", s.p, s.c, s.m);
}
Output:
1 -3 3
Why is the first value printed as 1 and the second value is printed as -3?
For p, you are allocating 4 bits. Therefore your valid range of values for p is 1000B - 0111B or -8 to 7. The fewest number of bits needed for -15 is 5 which in binary would be 10001B. Since you only allocated 4 bits, the sign bit is lost and you are left with 1.
For c, your are allocating 3 bits which has a valid range of 100B - 011B or -4 to 3. Since 5 is 101B and outside the valid range, it is displayed as -3.
The value 5 in binary is 101. Because the field in question is a 3 bit signed, and the most significant bit is set, the value is negative. In two's complement representation, it is -3.

Resources