深度剖析整型在内存中的存储
我们知道一个变量的创建是要在内存中开辟空间的,空间的大小是根据不同的类型而决定的,而且不同的类型也影响着我们看待内存空间的视角。
比如:int a = 20,float b= 5.0
接下来我们看看数据在所开辟的类型中是如何存储的?
整型在内存中的存储
整型家族
charunsigned char,signed char
shortunsigned short,signed short
intunsigned int,signed int
longunsigned long,signed long
原码、反码、补码
- 原码: 直接将二进制按照正负数的形式翻译成二进制即可
- 反码: 原码的符号位(用0表示正,用1表示负)不变,其他位依次按位取反
- 补码: 反码加1
对整型来说:数据存放内存中其实存放的是补码(正数的原反补码都相同)
原因是:1.符号位和数值位可以统一处理。2.加法和减法可以统一处理(CPU只有加法器)。3.补码与原码相互转换,运算过程也是相同的,不需要额外的硬件电路。16进制存放
我们发现对a和b分别存放的是补码,但顺序有点不对劲,这又是为什么呢?
大端和小端
-
大端存储模式:数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中。
-
小端存储模式:数据的地位保存在内存的低地址中,数据的高位保存在内存的高地址中。
内存中从左到右依次是由低地址到高地址
-
设计一个程序来判断当前机器的字节序
#include <stdio.h>
int check()
{
int x = 1;
return (char)x;//强制类型转换,保留最低位的一个字节。
}
int main()
{
int ret = check();
if (ret == 1)
{
printf("小端");
}
else
{
printf("大端");
}
return 0;
}
下面程序输出什么?
练习题1:
#include<stdio.h>
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a=%d\nb=%d\nc=%d\n", a, b, c);
return 0;
}
运行结果:
a=-1,b=-1,c=255
解析:
唯一的不同点就是a,b,c 的类型不同,输出结果却有如此大的差异。
将-1(int)2进制为11111111 11111111 11111111 11111111
的值赋给char类型时首先发生的时整型的截断,char接收到的只是-1最低位的一个字节2进制为:1111 1111
。
printf输出时以%d的形式输出cahr类型会发生整型的提升,发生提升时,有符号数高位补符号位,无符号数高位补0。有符号数a的补码为:11111111 11111111 11111111 11111111
有符号数b补码为:11111111 11111111 11111111 11111111
无符号数c补码为:00000000 00000000 00000000 11111111
练习题2:
#include<stdio.h>
int main()
{
char a = -128;
printf("%u\n", a);
return 0;
}
运行结果:
4294967168
解析:
首先根据a的原码写出a的补码
根据整型的截断,char接收到的是a最低位的一个字节 2进制为:1000 0000
打印时%u为无符号整型,则cahr a发生整型提升 无符号数a的补码为:11111111 11111111 11111111 10000000
无符号数的补码=原码。
练习题3:
#include<stdio.h>
#include<string.h>
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d\n", strlen(a));
return 0;
}
运行结果:
255
解析:
strlen求字符串长度,实质找的是’\0’的位置,即a = 0时。
i从0开始到999,a[i]接收值从-1到-1000,char a [i]会发生整型的截断,低位一个字节为 0000 0000
时,即求出字符串长度。(注意‘\0’不计入字符串长度)
i = 0时 -1截断之后为:1111 1111
i = 1时 -2截断之后为:1111 1110
i = 2时 -3截断之后为:1111 1101
当达到 0000 0000
时i = 255(下标),则字符串长度为0到254,输出255。
上一篇: QT5 使用163邮箱发送邮件