数据在内存中的存储(整型篇)

目录

1.数据类型的介绍

1.1C语言中的内置类型

1.2类型的意义

1.3类型的基本归类 

2.整型在内存中的存储

2.1数值的表示形式

2.2原码、反码、补码 

2.3整型的存储 

3.大小端存储模式


1.数据类型的介绍

1.1C语言中的内置类型

数据类型字节长度(sizeof)
char1
short2
int4
long(long int)4/8
long long8
float4
double8

注:

1.对于long型数据的字节长度,规定sizeof(long)>= sizeof(int)

2.long long是C99标准中新引进的数据类型,是64位的长整型数据类型

3.C语言中有没有字符串类型?

        答:C语言中没有原生的字符串类型,通过字符指针间接实现对字符串的操作

1.2类型的意义

  • 类型决定了使用这个类型开辟内存空间的大小,大小决定我们可使用的空间

如上图,一个创建一个整型变量时,就会在内存中开辟4个字节的空间,一个字符型的数据在内存中开辟1个字节的空间,一个float型的数据在内存中开辟4个字节的空间,其他数据类型同理。当我们使用时也只能使用所开辟空间中的数据、 

  • 类型决定如何看待内存空间的视角

这点我们通过以下整型数据在内存中的存储来讲解

1.3类型的基本归类 

  • 整型家族

char     unsigned char     signed char 

注:
  1. 为什么把字符型划分为整型? 因为字符的本质时ASCII码,是整型
  2. char是unsigned char还是signed char是标准未定义的,取决于编译器

int(signed int)     unsigned int   

注:

  1. 生活中有些数据是没有负数的,例如身高、体重等;但有些值是有负数的,例如温度等,所以产生了有符号整数和无符号整数
  2. 对于一个整型变量a,它在内存中占4个字节的长度,也就是32个比特位

  • 浮点数家族

float     double

注:

  1. 表示小数时使用浮点型
  2. float的精度低,存储的数值的范围较小;double的精度高,存储的数值的范围较大
  • 构造类型
  1. 数组类型
  2. 结构体类型struct
  3. 枚举类型enum
  4. 联合类型union
  • 指针类型
  • 空类型:常用于函数的返回类型,函数参数,指针类型等

2.整型在内存中的存储

2.1数值的表示形式

数值的表示形式:二进制、八进制、十进制、十六进制

例:一个十进制数21

二进制形式:0b10101(前缀0b代表为二进制的写法)

八进制形式:025(前缀为0代表为八进制的写法)

十六进制形式:0x15(前缀为0x代表为十六进制的写法)

对于进制表示的序列,每一位数字都有其所占的权重,二进制序列的各位权重如上图,其他进制下同理。并且进制之间是可以相互转换的。 

2.2原码、反码、补码 

对于整数的二进制序列 也有三种表示形式:原码、反码、补码

原码:直接通过正负写出的二进制序列

反码:符号位不变,其它位按位取反

补码:反码加一

正整数的原码,反码,补码相同,负整数的原码直接写出,反码和补码通过上述步骤计算

例:int a=20;int b=-10;

20的原码/反码/补码:00000000 00000000 00000000 00010100

-10的原码:10000000 00000000 00000000 00001010

-10的反码:11111111 11111111 11111111 11110101  

-10的补码:11111111 11111111 11111111 11110110

2.3整型的存储 

我们继续以 int a=20;int b=-10为例

对于a的原码/反码/补码:0000 0000 0000 0000 0000 0000 0001 0100

这个二进制序列的每四位表示一位十六进制位

写成十六进制的形式:0x 00 00 00 14

-10的原码:1000 0000 0000 0000 0000 0000 0000 1010

十六进制:0x 80 00 00 0a 

-10的反码:1111 1111 1111 1111 1111 1111 1111 0101  

十六进制:0x ff  ff ff f5

-10的补码:1111 1111 1111 1111 1111 1111 1111 0110

十六进制:0x ff  ff ff f6

调试起来后,我们打开内存监视窗口,可以观察到:整型数据在内存中以二进制补码序列存储,并且是倒着存放的,这就是大小端问题,以下我们会进行讲解。

为什么使用补码存放,而不使用原码呢?

  1. 使用补码,可以将符号位和数值域统一处理
  2. 加法和减法可以统一处理
  3. 补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路

例:1+1----->1+(-1)

 1的补码:00000000 00000000 00000000 00000001

-1的补码:11111111 11111111 11111111 11111111

补码相加后:1 00000000 00000000 00000000 00000000

我们知道整型是四个字节,32个比特位,所以这里超出的高位丢弃

结果是:00000000 00000000 00000000 00000000

最高位为0,是一个正整数,原码反码和补码相同,所以结果为0 

对于补码我们是对原码除符号位取反再加一,通过逆运算,我们可以由补码得到原码,其实,补码除符号位取反再加一同样可以得到原码

-10的原码:10000000 00000000 00000000 00001010

-10的补码:11111111 11111111 11111111 11110110

补码除符号位取反:10000000 00000000 00000000 00001001

加一:10000000 00000000 00000000 00001010(原码)

3.大小端存储模式

在上述例子中,我们提到整型数据在内存中以二进制补码序列存储,并且是倒着存放的

实际上,整型数据在内存中是以字节为单位存储的

例如0x 11 22 33 44,其中,11为高字节序,44为低字节序

大端字节序存储模式:把一个数据的高位字节序的内容存放在低地址处,把低位字节序的内容存放在高地址处

小端字节序存储模式:把一个数据的高位字节序的内容存放在高地址处,把低位字节序的内容存放在低地址处

我们通过图展示

 所以在VS中,倒着存是小端字节序存储方式

最后,我们浅做一个练习题:写一个程序判断当前机器是大端还是小端存储模式

分析:

以1为例:int a=1;

十六进制形式:0x 00 00 00 01

大端存储模式:00 00 00 01

小端存储模式:01 00 00 00 

我们只需要判断第一个字节,为0则是大端存储模式,为1则是小端存储模式

如何只访问第一个字节的内容?

我们知道int型数据的字节长度是4byte,char型数据的字节长度是1byte

对于一个char型数据我们只能访问内存中一个字节

&a得到的是指向a的指针,(char*)&a 将指向a的指针强制类型转换为char*型,再解引用,这样我们就只能访问一个字节的空间了

具体函数实现代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int check_sys(int a)
{
	return *(char*)&a;
}
int main()
{
	int a = 1;
	int ret = check_sys(a);
	if (ret == 1)
		printf("小端存储模式\n");
	else
		printf("大端存储模式\n");


	return 0;
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值