【C 数据存储详解】(1)——深度剖析整形数据在内存中的存储

简介: 【C 数据存储详解】(1)——深度剖析整形数据在内存中的存储

今天我们一起来学习一下C语言中的整型数据是如何在内存中存储的!!!


一.数据类型介绍

1.类型的意义

我们已经学习过了一些基本的内置类型:


char //字符数据类型

short //短整型

int //整形

long //长整型

long long //更长的整形

float //单精度浮点数

double //双精度浮点数


以及他们所占存储空间的大小(单位是字节):

#include <stdio.h>
int main()
{
    printf("%d\n", sizeof(char));
    printf("%d\n", sizeof(short));
    printf("%d\n", sizeof(int));
    printf("%d\n", sizeof(long));
    printf("%d\n", sizeof(long long));
    printf("%d\n", sizeof(float));
    printf("%d\n", sizeof(double));
    printf("%d\n", sizeof(long double));
    return 0; }

d0933bd8e0734138bfea1050853ed15a.png

C语言规定了这么多不同的数据类型,那么它们有什么意义呢?


1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。

2. 如何看待内存空间的视角。

2.类型的基本归类

下面我们对C语言中的数据类型做一个基本的归类:

(1).整型家族


1.char

unsigned char

signed char


2.short

unsigned short [int]

signed short [int]


3.int

unsigned int

signed int


4.long

unsigned long [int]

signed long [int]


这里大家可能会有疑惑,char不是字符类型吗?为啥归到整型里面了。


这是因为每个字符都有对应的ASCII码值,这些字符在内存中存储的时候,实际就是存放的ASCII码值,而ASCII码值都是整数,所以将char也归类到整型里面了


在这里还要给大家提醒一点,就是:


对于char来说,C语言本身并没有明确规定我们定义一个char类型的变量,它到unsigned char 还是 signed char 。 这个取决于编译器,不同的编译器情况可能不同,但是在绝大多数编译器上都是signed char 。

但是,对于short,int,long ,C语言规定了

1.short 就是signed short

2.int 就是 signed int

3.long 就是 signed long


(2).浮点数家族


float 单精度浮点型

double 双精度浮点型


(3).构造类型


数组类型

结构体类型 struct

枚举类型 enum

联合类型 union


(4).指针类型


int pi;

char pc;

float pf;

void pv;

0df6da820ea54658a3f0aa523d65778a.png

(5).空类型


void 表示空类型(无类型)

通常应用于函数的返回类型、函数的参数、指针类型


二.详解整型在内存中的存储

我们之前讲过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。


那接下来我们谈谈数据在所开辟内存中到底是如何存储的?

比如:

int a = 20;
int b = -10;

我们知道为 a 分配四个字节的空间。

那如何存储?

来了解下面的概念:


1. 原码、反码、补码

计算机中的整数有三种2进制表示方法,即原码、反码和补码。

三种表示方法均有符号位和数值位两部分:

符号位都是用0表示“正”,用1表示“负”。

而数值位:

正数的原、反、补码都相同。

负整数的三种表示方法各不相同。


下面来介绍一下什么时是原码、反码、补码:

原码:


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


补码:


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


反码:


反码+1就得到补码。


举个例子:

f00415cb0880456c80c05937fd6d8377.png

再看一个负数:

c9ba3f76ad544acdb98724c2493dac35.png

整数的2进制表示方法有原码、反码和补码,那内存中存的到底是啥哪?


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


为什么呢?


在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;

同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的

,不需要额外的硬件电路。


下面来解释一下:


1. 可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理


因为CPU只有加法器,所以对于1-1这样的表达式CPU要处理成1+(-1)来进行计算的。

而如果直接将两个操作数的原码进行相加,是可能会出错的:

举个例子:

1a8753b321574cf68b1df88e43bf7c74.png

1+(-1),我们用原码相加,得到错误的结果

用补码计算:

f2106145e58e4debb3e6c092bf93b022.png

最终用补码相加得到的结果才是正确的!!!


2.补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。


我们通过原码得到补码的方法是:

原码的符号位不变,其它位按位取反得到反码,反码加1,得到补码;

其实补码转到原码也可以用同样的方法。


然后我们创建两个变量,看一下,内存给我们展示出来的是什么样子的:

db0b1f1bd122469da0769102e3bb6ce2.png

我们可以看到对于a和b分别存储的是补码。但是我们发现顺序有点不对劲,好像是相反的。

这是又为什么?


2.大小端介绍

上面我们发现,对于a和b分别存储的是补码。但是我们发现顺序有点不对劲,好像是相反的,为什么?


学完下面的内容,我们就清楚了。

什么大端小端:


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


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


解释一下:

5badc71ca232421c9523aa2dae23800f.png

现在再看这张图我们就明白为什么顺序有点不对劲了。

4926b95dded643e5bfe618365d5d39f2.png

因为在vs2022上,采用的是小端存储模式。


那为什么会有大小端呢?


为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元

都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。


例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。


3.百度2015年系统工程师笔试题讲解

那么我们接下来做一道练习题,这道题是百度2015年系统工程师笔试题:


请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。


概念我们上面已经说过了,那怎么设计程序呢?我们来思考一下:


我们可以用整数1来帮助判断,取出1的第一个字节的内容,1的补码是:00000000000000000000000000000001,16进制是:00 00 00 01;

如果第一个字节的值是0(高位在低地址),则为大端;

如果第一个字节的值是1(低位在低地址),则为小端。

(注:我们取出的第一个字节是处在低地址的那一个字节)

afefa61b4ef842408d7feda9c454f1a0.png

上代码:

#include <stdio.h>
int main()
{
  int a = 1;
  if ((*(char*)&a) == 1)
    printf("小端");
  else
    printf("大端");
  return 0;
}

我们已经知道了vs上是小端,我们来一下看结果对不对:

72436107aa964b1f86dd1da538bfcca1.png

以上就是对整型在内存中如何存储的详细介绍,欢迎大家指正,我们一起进步!!!

00f04406d8ba4137945e709d108e6f55.png


目录
相关文章
|
5天前
|
存储 编译器 C语言
C语言:数据在内存中的存储形式
C语言:数据在内存中的存储形式
|
1月前
|
存储 搜索推荐 编译器
C learning_11 (数组和在内存存储的理解、数组越界、数组作为形参)
C learning_11 (数组和在内存存储的理解、数组越界、数组作为形参)
|
1月前
|
存储
数据在内存中的存储
数据在内存中的存储
30 0
|
1月前
|
存储 C语言
[C语言]数据在内存中的存储(浮点数篇)
[C语言]数据在内存中的存储(浮点数篇)
31 0
|
29天前
|
Linux
|
1月前
|
监控 关系型数据库 MySQL
innodb_buffer_pool_instances 如何根据cpu和内存进行配置
`innodb_buffer_pool_instances` 是用于配置 InnoDB 缓冲池实例数的参数。每个实例都管理缓冲池的一部分,这有助于提高并发性能。通常,你可以根据系统的 CPU 和内存来调整这个参数,以获得更好的性能。 以下是一些建议和步骤,帮助你根据 CPU 和内存进行 `innodb_buffer_pool_instances` 的配置: 1. **了解系统资源:** 首先,了解系统的硬件资源,特别是内存和CPU。检查系统上可用的物理内存和 CPU 核心数量。 2. **考虑每个实例的大小:** 在配置 `innodb_buffer_pool_instances` 时,
|
2天前
|
弹性计算 大数据 测试技术
阿里服务器租用多少钱一年?阿里云服务器租用价格表(最新CPU/内存/带宽/磁盘收费标准)
阿里服务器租用多少钱一年?阿里云服务器租用价格表(最新CPU/内存/带宽/磁盘收费标准)。阿里云服务器的租用费用因实例类型、地域、配置等因素而有所不同,价格范围可以从几百元到几千元不等。2024年阿里云服务器租用费用价格表更新,云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实
|
2天前
|
弹性计算
2024阿里云幻兽帕鲁/Palworld服务器价格表(CPU/内存/带宽/磁盘收费标准)
2024年阿里云幻兽帕鲁专用服务器的价格根据不同的配置有所不同。 • 4核16G配置的价格为32元/月,如果选择购买3个月,则价格为96元。 • 8核32G配置的价格为90元/月,如果选择购买3个月,则价格为271元。 另外,还有配置为4核16G10M带宽的服务器,其价格为26元/月起。而8核32G10M带宽的价格也是90元/月。
17 1
|
4天前
|
弹性计算 大数据 测试技术
2024阿里云服务器租用价格表(CPU/内存/带宽/磁盘收费标准)
阿里云服务器分为轻量应用服务器和云服务器ECS,轻量适合个人开发者使用,搭建轻量级的网站、测试环境使用;专业级如大数据、科学计算、高并发网站等需要使用云服务器ECS。2024年阿里云服务器租用价格表出炉!云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实例、ECS计算型c7、通
|
9天前
|
弹性计算 大数据 测试技术
2024年阿里云服务器租用价格表(CPU/内存/带宽/磁盘收费标准)
2024年阿里云服务器租用价格表更新,云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年,轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服务器30元3个月,幻兽帕鲁4核16G和8核32G服务器配置,云服务器ECS可以选择经济型e实例、通用算力u1实例、ECS计算型c7、通用型g7、c8i、g8i等企业级实例规格。阿里云百科分享阿里云服务器租用费用最新报价

热门文章

最新文章

相关产品

  • 云迁移中心