当前位置:网站首页>数据在内存中的存储方式(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;
}边栏推荐
- 快速认识 WebAssembly
- mysql 优化
- 杂七杂八的东东
- 如何查看本机IP
- idea自动生成serialVersionUID
- 30 data visualization tips that can not be ignored
- 2.17 haas506 2.0开发教程-system(仅支持2.2以上版本)
- Get to know webassembly quickly
- Test of ers function under the supplier consignment purchase mode of SAP mm
- Problem: when the attribute in the data object (defined data) in the access component is also the attribute in the object object, an error is reported
猜你喜欢

Summary of qvariant use in QT

Programmers' real ideas | daily anecdotes

Copy and paste of idea without escape

mysql 优化

MySQL ON DUPLICATE KEY 和 PgSQL ON CONFLICT(主键) 处理主键冲突

Functions and basic structure of CPU

如何迁移virtualbox 的虚拟机到hype-v

haas506 2.0開發教程-高級組件庫-modem.sms(僅支持2.2以上版本)

mysql 基础查询

Easy EDA #学习笔记09# | ESP32-WROOM-32E模组ESP32-DevKitC-V4开发板 一键下载电路
随机推荐
asp.net文件下载demo与相关问题的处理
[resolved] "the unity environment took too long to respond. make sure that: \n“
Haas506 2.0 development tutorial - Advanced Component Library -modem Net (only supports versions above 2.2)
了解学习 JSX 的工作方式
总结的好处
Haas506 2.0 development tutorial -hota (only supports versions above 2.2)
haas506 2.0开发教程-高级组件库-modem.sms(仅支持2.2以上版本)
/bin/sh no such file or directory问题
Understand how learning JSX works
Usage Summary of item views and item widgets controls in QT
Coordinate transformation
Focusing on the smart city, Huawei cooperates with China Science and technology Xingtu to jointly develop a new digital blue ocean
Explain csma/cd, token bus and token ring clearly
嵌入式实时系统线程的副作用
MySQL5.6 (5.7-8) 基于shardingsphere5.1.1 Sharding-Proxy模式读写分离
leetcode - 572. 另一棵树的子树
项目_过滤器Filter解决中文乱码
mingw-w64、msys和ffmpeg的配置与编译
Termux
2.17 haas506 2.0 development tutorial system (only versions above 2.2 are supported)