整数在内存中的存储形式,大小端

1.整数在内存中的存储

在讲解操作符的时候,我们就讲过了下⾯的内容:

整数的2进制表⽰⽅法有三种,

即 原码、反码和补码

三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表⽰“负”,⽽数值位最 ⾼位的⼀位是被当做符号位,剩余的都是数值位。

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

负整数的三种表⽰⽅法各不相同。

  1. 原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
  2. 反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
  3. 补码:反码+1就得到补码。

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

为什么呢? 在计算机系统中,数值⼀律⽤补码来表⽰和存储。 原因在于,使⽤补码,可以将符号位和数值域统⼀处理; 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是 相同的,不需要额外的硬件电路。

2.⼤⼩端字节序和字节序判断

当我们了解了整数在内存中存储后,我们调试看⼀个细节:

#include <stdio.h>
int main()
{
 int a = 0x11223344;
 
 return 0;
}

 我们发现内存里存的怎么是44332211呢?别着急,我们马上解释 

 2.1.大小端

C语言中的大小端(Endianness)指的是字节顺序的不同方式,即如何将多字节的数据类型(如整数、浮点数)在内存中存储。

2.1.1高低位

先来了解数字的高低位

0x12345678

越靠近1这边的位就叫高位,越靠近8那边的位叫低位

2.1.2高低地址

什么是高地址,什么是低地址,举举例说明?

可以把主存看成一本空白的作业本,你现在要在笔记本上记录一些内容,他的页码排序是

第一页 : 0x0000001
第二页 : 0x0000002
…
最后一页: 0x0000092

1 如果你选择从前向后记录(用完第一页,用第二页,类推)这就是先使用低地址,后使用高地址.

0x0000001 -> 0x0000002-> … -> 0x0000092

业内有这样表述:动态分配内存时堆空间向高地址增长,说的就是这种情况.
这个向高地址增长就是先使用低地址,后使用高地址的意思.

2 如果你选择从后往前记录(先用笔记本的最后一页,用完后使用倒数第二页,类推) 这就是先使用高地址,后使用低地址

0x0000092 -> … ->0x0000002 -> 0x0000001

业内表述:0xbfac 5000-0xbfad a000是栈空间,其中高地址的部分保存着进程的环境变量和命令行参数,低地址的部分保存函数栈帧,栈空间是向低地址增长的.

这个向低地址增长就是先使用高地址,后使用低地址的意思.

2.1.3区分高低地址和高低位

高地址低地址容易与高位低位产生混淆.

比如我这个月工资为1234(一千二百叁拾肆块),那么这串数字的左边我们称呼为高位,右边称为低位.
 

(这个高低来自于人类的阅读习惯,数字从左向右,表示由大到小)

在计算机中以int类型存储工资,假设int占用四个字节,每个字节地址如下

0x00008
0x00009
0x0000a
0x0000b

把工资加载到内存中时,就会有两种存储方式,如下:

// 大端法
0x00008 => 1
0x00009 => 2
0x0000a => 3
0x0000b => 4

如果把上边的存储方式反过来,内存中的高地址存储工资中的高位,则称为小端法 

或者

// 小端法
0x00008 => 4
0x00009 => 3
0x0000a => 2
0x0000b => 1

内存中的低地址存储工资中的高位这种方式称为大端法.

(注释:可以采用异或方法来记忆 低地址存低位为小端法).

主机采用大端还是小端表示数据由CPU的架构决定,如果两个主机只见交互数据,但是字节序表示不同,需要同化.

2.2.小端字节序存储(Little Endian):

在小端字节序中,最低有效字节存储在最低地址,最高有效字节存储在最高地址

例如,整数值0x12345678在内存中的存储方式如下:

低地址 ─────> 高地址
78 56 34 12

这种字节顺序在x86架构的计算机上被广泛使用,包括大部分的个人电脑和服务器。

2.3.大端字节序存储·(Big Endian):

在大端字节序中,最高有效字节存储在最低地址,最低有效字节存储在最高地址。

例如,整数值0x12345678在内存中的存储方式如下:

低地址 ─────> 高地址
12 34 56 78

这种字节顺序在一些嵌入式系统和网络协议中使用较多。

2.4.为什么会有大小端?

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为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处理器还可以由硬件来选择是 ⼤端模式还是⼩端模式。

简单点说就是硬件厂商各有所好,并没有统一的约定制作制作哪一个,

  1. 大端的优势在于第一个字节就是高位,很容易判断正负性。
  2. 小端的优势在于第一个字节是低位,最后一个字节是高位,可以依次取出相应的字节进行运算,并且最终会把符号位刷新,这样运算起来更高效。

2.5.如何确定大小端?

当我们不知道当前换将是大端存储还是小端存储的时候,就需要用代码来确定当前环境的大小端,下面给出了两种确定大小端的方式:

2.5.1共用体确定大小端

    共用体里面的变量是公用一块空间的,

int a = 0x11 22 33 44占据了四个字节,

假设是小端第一个字存的就是数据的低位0x44 ,char c只占据了第一个字节

#include<stdio.h>

union U
{
int a;
char c;
};
 
int A()
{
    union U u;
    u.a = 0x11223344;
    if (u.c == 0x44) 
    {
        return 1;
    }
    else
        return 0;
}
 
 
 
int main()
{
    int i = A();
    if (i == 1)
    {
        printf("小端模式\n");
    }
    else
    {
        printf("大端模式\n");
    }
 
    return 0;
}

在我的设备上运行结果如下


2.5.2指针确定大小端 

        强制类型转换会发生截取,下面用char*强制类型转换,截取了第一个字节的地址,然后解引用读取了第一个字节的数据。

#include<stdio.h>

int B()
{
    int i = 0x11223344;
    if (*(char*)(&i) == 0x44)
    {
        return 1;
    }
    else
        return 0;
}
 
int main()
{
    int i = B();
    if (i == 1)
    {
        printf("小端模式\n");
    }
    else
    {
        printf("大端模式\n");
    }
 
    return 0;
}

  • 59
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 31
    评论
### 回答1: 在 C 和 C++ ,int 类型在内存是以二进制形式存储的,它占用固定的内存空间,一般情况下占用 4 个字节。 int 类型的值在内存是以补码的形式存储的,即对于一个整数来说,它的补码是其原码取反加一。例如,如果一个 int 变量的值为 10,那么在内存存储的就是 10 的补码,即 0101 取反加一得到 1010。 这样做的原因是为了方便在计算机实现负数的运算,因为计算机的数据都是以二进制形式存储的,如果直接将负数的原码存储内存,那么在进行负数的运算时会比较麻烦。但是如果使用补码的形式存储负数,那么就可以使用相同的方式来处理正数和负数,这样就可以大大简化计算机的设计。 ### 回答2: int在内存存储方式取决于所使用的计算机体系结构和编译器的实现方式。一般来说,int在内存是以二进制补码的形式存储的。 在大多数计算机体系结构,int被存储为一个固定的字节大小,通常是4个字节(32位)或8个字节(64位)。其最低有效字节存储int的最低有效位,以下字节按照顺序存储整数的高位。 例如,考虑一个32位的int值300。以十六进制表示为0x0000012C。在内存,这个int值通常会被存储为4个连续的字节,如下所示: 地址 内容 ------- -------- 0x1000 0x2C 0x1001 0x01 0x1002 0x00 0x1003 0x00 这个例子,最低有效字节0x2C存储在最低地址0x1000处,而最高有效字节0x00存储在最高地址0x1003处。这种存储方式可以通过指针来访问和操作int值。 需要注意的是,不同的计算机体系结构可能有不同的字节顺序(即大序和小序)。在大,最高有效字节存储在最低地址处;而在小,最低有效字节存储在最低地址处。因此,在不同的计算机体系结构,对于相同的int值,在内存存储方式可能会有所不同。 总之,int在内存以二进制补码形式存储,使用固定的字节大小,并且根据计算机体系结构的字节顺序进行存储。 ### 回答3: 在内存,int被存储为连续的二进制位,通常为32位或64位,具体取决于处理器的架构。每个二进制位(或称为比特)可以表示0或1。 对于有符号整数来说,最高位被用作符号位。如果最高位为0,则表示该整数为正数;如果最高位为1,则表示该整数为负数。其余的二进制位用来表示整数的数值部分。 例如,对于32位的int,最高位用来表示符号,剩下的31位用来表示整数的数值部分。这意味着一个32位的int可以表示范围为-2,147,483,648到2,147,483,647的整数。 在内存,int的存储通常是按照小序(Little-Endian)或大序(Big-Endian)的方式进行的。小序表示数值的最低有效字节存储在最低的地址处,而大序则是将数值的最高有效字节存储在最低的地址处。 例如,十进制数字12345678以小存储时,在内存存储顺序为:0x4E(低地址) 0x61 0xBC 0x00(高地址)。 总之,int在内存以二进制形式存储,并且具有符号位来表示正负号。存储顺序可以是小序或大序,具体取决于处理器的设置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值