一.整数在内存中的存储
1.原码,反码,补码的概念
int a = 20;
int b = -10;
我们知道会为 a 和 b各分配4个字节的空间,那如何存储呢?
首先我们先了解一下原码,反码,补码的概念:
计算机中的有符号数有三种表示方法,即原码、反码和补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位三种表示方法各不相同。
原码:
直接将二进制按照正负数的形式翻译成二进制就可以。
反码:
将原码的符号位不变,其他位依次按位取反就可以得到了。
补码:
反码 + 1得到补码
正数的原、反、补码都相同。
对于整形来说:数据存放内存中其实存放的是补码。
我们可以看到内存中的确存放的是补码,但细心的读者一定可以发现补码字节的顺序是反的。
2.字节序
大小端介绍:
大端字节序存储 模式,是指数据的低位字节保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端字节序存储 模式,是指数据的低位字节保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
了解了大小端以后,我们来看一道题:
设计一个小程序来判断当前机器的字节序
#include<stdio.h>
int check_sys()
{
int a = 1; // 0x 00 00 00 01
return *(char*)&a;
}
int main()
{
if (check_sys() == 1)
printf("小端\n");
else
printf("大端\n");
}
我们可以发现只要我们判断出第一个字节的内容是1还是0就可以判断出机器的字节序了
因此我们只需要访问一个字节即可。
二.练习
(1)
//输出什么?
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
(2)
// 输出什么?
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
(3)
// 输出什么?
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
(4)
#include<stdio.h>
int main()
{
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
//按照补码的形式进行运算,最后格式化成为有符号整数
return 0;
}
(5)
#include<stdio.h>
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
return 0;
}
(6)
#include<stdio.h>
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
(7)
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
// 死循环打印hello world
i = 256 时,截断放在unsigned char 里面是 00000000
因此开始死循环