当前位置:网站首页>数据在内存中的存储方式(C语言)
数据在内存中的存储方式(C语言)
2022-06-23 05:56:00 【浪雨123】
C语言给定了一些基本的数据类型
char 类型
int 类型
long 类型
float 类型
double 类型
前三者都属于整型家族,后两者属于浮点型家族,为什么char属于整型家族呢?这是因为字符是以对应的ASCII码值存放到内存中,本质上是属于整数的,所以将其归类为整型。
那么我们在创建这些变量且赋予它们具体数值的时候,它们又是如何将这些数值数据存放到内存中的呢?我们都知道任何形式的数据(字符,图片, 音频......)放到电脑中都是以二进制的形式存放的
例如 我们创建一个整型变量,并赋予它一个数值
int a = 10;
a中的数据放在内存中需要转化为二进制形式
将10转化为二进制形式为 1010 因为int有32个比特位的大小,所以最终的形式如下
00000000000000000000000000001010这样我们就解决了存放整数的问题,但很快会发现,如果存放一个负整数该怎么存呢?该怎么表示这个数字是负的呢?聪明的科学家想到了这样一个办法,那就是将这个二进制序列的最高位定义为符号位,如果最高位上的数字为0,那表示这个数字是正数,如果最高位上的数字为1,那表示这个数字是负数,例如下面的表示
int a = 10;
a中的数据放在内存中转化为二进制形式为
00000000000000000000000000001010
int a = -10;
a中的数据放在内存中转化为二进制形式为
10000000000000000000000000001010
好了,现在正整数和负整数在内存中存放的形式都解决了,哈哈,不过问题又来了,正整数和负整数在进行加减运算的时候就出现问题了,如下
int a = 10;
int b = -1;
a 在内存中的二进制形式为 00000000000000000000000000001010
假设 b 在内存中的二进制形式为 10000000000000000000000000000001
如果将a 与 b 相加
a 00000000000000000000000000001010
+
b 10000000000000000000000000000001
= 10000000000000000000000000001011a和b相加,结果却变成了 -11,怎们办,这里不得不佩服科学家的聪明,引入了原码 补码 反码的概念,那么这些具体有什么作用呢?接下来分析一下。
正数的原码 反码 补码相同
int a = 10;
a 的二进制形式为
00000000000000000000000000001010 //原码
00000000000000000000000000001010 //反码
00000000000000000000000000001010 //补码
负数的反码为 原码的符号位不变,其他位取反。负数的补码为反码加1
int b = -10;
b 的二进制形式为
10000000000000000000000000001010 //原码
11111111111111111111111111110101 //反码
11111111111111111111111111110110 //补码
这里需要知道的是,无论正数还是负数,都是以补码的二进制序列放到内存中的
因此实际上,a放到内存中是补码 00000000000000000000000000001010
b放到内存中是补码 11111111111111111111111111110110,接下来我们通过编译器去验证一下。

验证结果是没有问题滴,说明确实是这样存储的,但至此,可能对其作用仍不了解,那接下来说一下反码 补码的具体的作用,还是以加法为例
int a = 10;
a 的二进制形式为
00000000000000000000000000001010 //原码
00000000000000000000000000001010 //反码
00000000000000000000000000001010 //补码
int b = -5;
b 的二进制形式为
10000000000000000000000000000101 //原码
11111111111111111111111111111010 //反码
11111111111111111111111111111011 //补码
因为都是以补码存放到内存中,所以在内存中
a 为00000000000000000000000000001010
b 为11111111111111111111111111111011
a 00000000000000000000000000001010
+
b 11111111111111111111111111111011
= 00000000000000000000000000000101
转化为十进制就是5 是不是很奇妙,这就是反码 补码的妙用,非常漂亮的的解决掉正负数进行加减运算的问题,其他的乘除运算都可以转化为加法运算,这样也就同时解决掉其他的运算问题。
这里补充一点,补码取反加1是可以转化为原码的
我们试一试
11111111111111111111111111111011 这是b的补码,现在我们符号位不动,其他位取反
10000000000000000000000000000100 这是补码取反后的结果,接下来我们把它加1
10000000000000000000000000000101 这是加1后的结果,发生什么事了,是不是又变回了原码接下来,举点栗子,加深对上面知识的理解
char a = -1; //注:char 是 signed char还是 unsigned char取决于编译器
signed char b = -1; //不过一般都是signed char
unsigned char c = -1;
printf("%d %d %u", a, b, c);
那么打印的结果分别是什么呢?
一起分析一下吧

以上就是整型数字在内存中的存储方式,但仔细观察下图,会发现一个奇怪的现象
就拿int a 来说 我们分析的存储方式应该是00 00 00 0a ,而编译器上却显示存储形式为0a 00 00 00
这其实就牵涉到大端,小端存储的问题,为什么会这样呢?因为int 类型接连占用四个字节,该空间的数据的存放位置就得有一个规定,我们同样可以将a中得数据以00 0a 00 00或者是00 00 0a 00的方式存储,但这些都太过麻烦了,00 00 00 0a 和 0a 00 00 00这两种存储方式最符合我们的思维习惯,就沿用至今,分别叫大端存储法和小端存储法。大端还是小端是取决于硬件的,与编译器无关,一般个人pc用的是小端存储法。
接下来我们一起分析一下大端与小端,然后再写个小程序来判断自己的设备采用的是大端还是小端

那我们怎么判断自己的设备是大端还是小端呢? 同样是 int a = 10; 我们想看看它是大端存放还是小端存放,只需查看该空间的第一个字节,因为空间的第一个字节是处于低地址的,如果该空间的第一个字节没有存放 0a 则说明是大端存放,如果存放了0a,则说明是小端存放。
代码实现如下
int main()
{
int a = 10;
char *p = (char*)&a;
if (10 == *p)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}边栏推荐
- Badly placed ()‘s 问题
- Programmers' real ideas | daily anecdotes
- DQL、DML、DDL、DCL的概念与区别
- haas506 2.0开发教程-hota(仅支持2.2以上版本)
- XXL-SSO 实现SSO单点登录
- Data indicators and data analysis models that designers need to understand
- xml schem 记录
- Qt使用多线程编译项目的方法
- SAP execution transaction code mrrl error -no message was found for partner 100065-
- Set tensorflow1 X to pytorch
猜你喜欢

Docker practice - redis cluster deployment and micro service deployment project

leetcode - 572. A subtree of another tree

Synchronous switching power supply reduces EMI layout dv/dt di/dt

Haas506 2.0 development tutorial -hota (only supports versions above 2.2)

How to realize video call and live interaction in a small program when live broadcasting is so popular?

redux Actions may not have an undefined “type“ property. Have you misspelled a constant?

Data indicators and data analysis models that designers need to understand

xml schem 记录

如何查看本机IP

解读创客教育中的团结协作精神
随机推荐
haas506 2.0开发教程-高级组件库-modem.sms(仅支持2.2以上版本)
Data indicators and data analysis models that designers need to understand
WPF Command指令和INotifyPropertyChanged
利用adb 调试设备串口信息的一个小方法
Copy and paste of idea without escape
idea安装 CloudToolkit 插件
Focusing on the smart city, Huawei cooperates with China Science and technology Xingtu to jointly develop a new digital blue ocean
mysql 基础查询
Topic35——34. 在排序数组中查找元素的第一个和最后一个位置
开源OAuth2框架 实现SSO单点登录
/bin/sh no such file or directory问题
mongodb 记录
ffplay实现自定义输入流播放
haas506 2.0开发教程-hota(仅支持2.2以上版本)
MySQL5.6 (5.7-8) 基于shardingsphere5.1.1 Sharding-Proxy模式读写分离
[resolved] "the unity environment took too long to respond. make sure that: \n“
【踩坑记录】数据库连接未关闭连接,释放资源的坑
Usage Summary of item views and item widgets controls in QT
C language removes line breaks (or other characters) at the end of strings
把CSMA/CD、Token Bus、Token Ring说清楚