数据在内存中的存储
首先我们需要先简单了解一下数据的原码、反码和补码。
正数的原码、反码和补码都是一样的。
而负数的反码则是原码符号位不变,其余为取反。反码加1就得到补码。
第一位为符号位,0表示正数,1表示负数。
10 的原码、反码和补码 |
---|
原码:00000000000000000000000000001010 |
反码:00000000000000000000000000001010 |
补码:00000000000000000000000000001010 |
-10 的原码、反码和补码 |
---|
原码:10000000000000000000000000001010 |
反码:111111111111111111111111111111110101 |
补码:111111111111111111111111111111110110 |
我们可以通过编译器得知内存中存放的是数据的补码。
额外补充:在计算机中,只进行加法运算。如果要进行减法运算,先转换成加法再运算。例如1 - 1就可以转换成1 + ( -1 )再运算。
大小端字节序
大端字节序和小端字节序: 数据存放在内存中的顺序分为大端字节序和小段字节序。
大端字节序:数据中的低地址内容存放在内存中的高地址处。
小端字节序:数据中的低地址内容存放在内存中的低地址处。
可以看出在visual studio中使用的是小端字节序存储数据的。
一道小题目
可以看看下面这段代码输出结果是多少?
#include <stdio.h>
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("%d %d %d\n", a, b, c);
return 0;
}
结果是 -1 -1 255
解析:
char a = -1
-1 的原码:10000000000000000000000000000001
-1 的反码:11111111111111111111111111111110
-1 的补码:11111111111111111111111111111111
而char只能存放8位,也就是补码的最后8位(11111111)。
signed char b= -1 和上面一样,也只能存放8位(有符号)unsigned char c= -1 存放8位(无符号)
结果在printf语句中,以%d形式将 a,b,c打印出来,发生了整型提升。
a和b都提升成11111111111111111111111111111111(有符号发生整型提升,前面补1,现在就是提升后的补码)
换成原码打印出来就是 -1,而无符号 c 整型提升(前面补0)就变成00000000000000000000011111111 结果就是255。
char 和 unsigned char 的取值范围
char 和 unsigned char 的取值范围可以看成一个循环,加法往下,减法往上。
在char(signed char)中运算:
127 + 1 = -128; -128 + 1 = -127; -128 - 1 = 127; -1 - 1 = -2;
在unsigned char中运算:
0 - 1 = 255; 127 + 1 = 128; 255 + 1 = 0;