Reputation: 671
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p_x = (int *)malloc(1 * sizeof(int));
scanf("%d", p_x);
for (int i = 0; i < 4; i++) {
char *one_byte_slice = (((char *)(p_x)) + i);
printf("slice : %d , value : %d\n", i, *one_byte_slice);
}
return 0;
}
When I entered positive values they seems understandable to me but for negative I don't understand it well.
For *p_x = 127
:
127
slice : 0 , value : 127
slice : 1 , value : 0
slice : 2 , value : 0
slice : 3 , value : 0
p_x ---> 0111 1111
0000 0000
0000 0000
0000 0000
For *p_x = 256
:
256
slice : 0 , value : 0
slice : 1 , value : 1
slice : 2 , value : 0
slice : 3 , value : 0
p_x ---> 0000 0000
0000 0001
0000 0000
0000 0000
For *p_x = -20
:
-20
slice : 0 , value : -20
slice : 1 , value : -1
slice : 2 , value : -1
slice : 3 , value : -1
p_x ---> 1001 0100
1000 0001
1000 0001
1000 0001
And for *p_x = -256
:
-256
slice : 0 , value : 0
slice : 1 , value : -1
slice : 2 , value : -1
slice : 3 , value : -1
p_x ---> 0000 0000
1000 0001
1000 0001
1000 0001
So how is it stored in memory for fixed point numbers is is stored in 2's complement or other way?
Upvotes: 1
Views: 955
Reputation: 12668
This is called low-endian encoding. The individual bit slices of the integer are stored from least significative to most significative in the consecutive byte cells. Your integer is represented in binary form as:
0000 0000 0000 0000 0000 0000 0111 1111
(where I have used a space to separate each group of four bits). Each byte is stored from the least significant group of eight bits to the most, in growing byte addresses, starting from the right above:
Addr. Value.
0000: 0111 1111
0001: 0000 0000
0002: 0000 0000
0003: 0000 0000
There's another way to do it, which is called big-endian, which stores the bytes just in the reverse direction, and some machines do it:
(Big-endian)
Addr. Value.
0000: 0000 0000
0001: 0000 0000
0002: 0000 0000
0003: 0111 1111
There are other ways to do, but today's computers normally use one of these two.
In the case of negative numbers, the solution consists in thinking that negative numbers and positive numbers are so that adding and subtrating can be done withou having to use an alternate circuitry. So numbers are divided in two halves and the ones with the most significant bit represent the negative ones... so numbers are represented (I'll use only four bits for brevity):
1000: -8
1001: -7
1010: -6
1011: -5
1100: -4
1101: -3
1110: -2
1111: -1
0000: 0
0001: 1
0010: 2
0011: 3
0100: 4
0101: 5
0110: 6
0111: 7
With 32 bits the result is the same, but extended to 32 bits... this makes that all the small negative numbers have all the most significant bits equal to 1
.
1000 0000 0000 0000: -2147483648
1000 0000 0000 0001: -2147483647
...
1111 1111 1111 1101: -3
1111 1111 1111 1110: -2
1111 1111 1111 1111: -1
0000 0000 0000 0000: 0
0000 0000 0000 0001: 1
...
0111 1111 1111 1100: 2147483644
0111 1111 1111 1101: 2147483645
0111 1111 1111 1110: 2147483646
0111 1111 1111 1111: 2147483647
in such a way that adding is jumping in the previous table downwards and subtracting going upwards. This is called two's complement encoding.
Upvotes: 1
Reputation: 671
Yeah i think i got my answer.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p_x = (int *) malloc(1*sizeof(int));
scanf("%d",p_x);
for(int i=0;i<4;i++) {
unsigned char *one_byte_slice = ( ((unsigned char *)(p_x)) + i);
printf("slice : %d , value : %hhx\n",i,*one_byte_slice);
}
return 0;
}
When i tried %hhx
and unsigned char *
it's shows me 2's
complement for negative values.
-1
slice : 0 , value : ff
slice : 1 , value : ff
slice : 2 , value : ff
slice : 3 , value : ff
p_x ---> 1111 1111
1111 1111
1111 1111
1111 1111
-3
slice : 0 , value : fd
slice : 1 , value : ff
slice : 2 , value : ff
slice : 3 , value : ff
p_x ---> 1111 1101
1111 1111
1111 1111
1111 1111
Yeah so conclusion is it's stored in 2's
complement format.
Upvotes: 0