【C语言】整型数据居然是这样存储的。

发布于:2023-01-23 ⋅ 阅读:(501) ⋅ 点赞:(0)

一 整型和浮点型两大家族

1整型家族

char
unsigned char
signed char
short
unsigned short [int]
signed short [int]
int
unsigned int
signed int
long
unsigned long [int]
signed long [int]

其中signed前缀的为有符号类型,有正负
unsigned类型为无符号类型,没有正负
unsigned short [int]中的int可以写也可以不写,short的本质是short int

2浮点型家族

float
double

二 整型(signed)存储方式

1.原码、反码、补码

(1) 定义:

1 我们都知道数据在计算机中是以二进制形式存储的,而原码、反码、补码正是二进制的三种表示形式。
2 三种方式均有符号位数值位两部分。在符号位中 0 表示正,用 1 表示负。三种码的第一位是符号位其余是数值位。
3 对于数值位:
正数的原码、反码、补码相同
负整数的三种表示方法各不相同

原码
直接将数值按照正负数的形式翻译成二进制就可以得到原码。

反码
将原码的符号位不变,其他位依次按位取反就可以得到反码。

补码
反码+1就得到补码。

对于整形来说:数据存放内存中其实存放的是补码。

(2) 例子:

让我们试着画一下10和-1的原码、反码、补码
在这里插入图片描述

2.大小端存储

(1) 定义

了解大小端存储之前我们先看一张图片
在这里插入图片描述
通过调试查看内存我们可以看到a的地址(地址均以十六进制的形式展示),我们发现a的地址好像倒过来了。根据上一张图片我们可以看到a的十六进制好像是0x 00 00 00 0a。为什么反过来了?
这时候就需要用到大小端存储的概念了。

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中.

所以我们发现了原因,因为我们的编译器是小端存储的模式,所以当编译器以字节为单位进行排序时原本在后面的0a(数据的低位)被排在了低地址处。

(2) 这样存储的原因

在计算机系统中,我们是以字节为单位的。变量类型不仅有包含一个字节的char类型还有包含多个字节的int,double等类型,那么就肯定会出现多字节排序的问题,这时候就出现了大小端存储模式。

(3) 如何证明大小端存储

让我们用一道老题来证明大小端存储的存在
在这里插入图片描述

#include <stdio.h>
int check_sys()
{
//由第一张图我们知道1的补码为00000000 00000000 00000000 00000001
	 int i = 1;
//当我们取i的地址时我们就得到了1的补码,此时我们将i强制转换为char*
//类型最后变为char类型,因为char只包含一个字节,所以我们只能返回8个
//bite位,若编译器为小端存储就正好能得到1。
	 return (*(char *)&i);
}
int main()
{
	 int ret = check_sys();//我们通过这个函数判断是大端还是小端
	 if(ret == 1)
	 {
	 printf("小端\n");
	 }
	 else
	 {
	 printf("大端\n");
	 }
 return 0; 
 }

注意unsigned类型没有符号位,所有位都是数值位。因此unsigned类型没有负数的情况,signed char类型范围是-128~127,unsigned char类型范围就是255.

让我们先看看怎样得到(signed) char类型变量的范围
在这里插入图片描述

三 关于整型存储的一些应用

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);//-1 -1 255
    return 0; 
}

-1本来为11111111,变为无符号类型之后开头的1也变成了数值位。因此结果就是2 ^ 8 - 1 = 255

2.
#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0; 
}

%u 是打印无符号整形,认为内存中存放的补码对应的是一个无符号数
%d 是打印有符号整形,认为内存中存放的补码对应的是一个有符号数

先将-128化为补码,但存入char类型会发生截断,-128截断后为10000000,
因为%u是打印整形,因此会发生整形提升,有符号类型按符号位提升,变成
11111111 11111111 11111111 10000000 又因为%u打印无符号整型这串数字直接变成单纯的二进制数。输入计算器计算。
在这里插入图片描述
结果为4294967168

注意:
无符号整型 整型提升是加0
有符号整型 整形提升加符号位