简单的数据在内存中的存储

目录

一.整数在内存中的存储

1.1原码,反码和补码

(1)原码

(2)反码

(3)补码

1.2 存储方式

二.大小端字节序和字节序判断

2.1 大小端字节序的概念

2.2 字节序判断 

三.练习 

练习1

练习2

练习3 

练习4 

练习5 

练习6 

后记 


一.整数在内存中的存储

1.1原码,反码和补码

(1)原码

原码是最直观的二进制表示方法,它直接反映了数的正负。对于正数,其原码就是该数的二进制表示(即符号位为0,其余各位为该数的绝对值二进制表示);对于负数,其原码则是符号位为1,其余各位为该数绝对值的二进制表示取反。

示例

+5的原码:0101(二进制)

-5的原码(按照直接定义):1101(注意,这里的1101并不是-5的绝对值4的二进制表示取反,而是直接表示-5)

(2)反码

反码是在原码的基础上,对于负数,将其符号位以外的所有位取反(即0变1,1变0)得到的。正数的反码就是其原码。

示例

+5的反码:0101(与原码相同)

-5的原码(按上述定义):1101,其反码为1010(仅对符号位以外的位取反)

(3)补码

补码是在反码的基础上加1得到的。补码是计算机中用于表示有符号整数的一种最常用的编码方式,因为它能够简化计算机中的加减法运算(尤其是涉及负数的运算)。补码的正数表示与原码和反码相同,而负数的补码则是其反码加1。

示例

+5的补码:0101(与原码、反码相同)

-5的反码为1010(基于上面的反码示例),其补码为1011(反码加1)

总结

原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。

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

补码:反码+1就得到补码。

补码的使用是现代计算机体系结构的基石之一,它使得计算机在处理有符号整数时更加高效和一致。

1.2 存储方式

整型数据:整型数据(如intshortlong等)在内存中通常以二进制补码的形式存储。补码是一种表示有符号整数的方式,可以高效地处理正负数的加减运算。

浮点型数据:浮点型数据(如floatdouble)的存储遵循IEEE 754标准,包含符号位、指数部分和尾数部分。

字符型数据:字符型数据(如char)在内存中通常以ASCII码或Unicode码的形式存储。

结构体和联合体:结构体(struct)和联合体(union)是复合数据类型,它们在内存中的存储方式取决于其成员的类型和顺序。结构体成员在内存中连续存储,而联合体在同一内存位置存储其最大成员的值。

指针:指针变量存储的是内存地址,即指向另一个变量的值。指针的大小取决于操作系统和编译器,通常是4字节(32位系统)或8字节(64位系统)。

二.大小端字节序和字节序判断

2.1 大小端字节序的概念

 其实超过⼀个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储,下面是具体的概念:

 大端(存储)模式: 是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容,保存在内存的低地址处。

小端(存储)模式: 是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。

2.2 字节序判断 

下面我们通过两段代码来实现字节序的判断

代码1

在这端代码中,我们通过函数check_sys来实现大小端字节序的判断。

check_sys函数通过将一个整型变量i的地址转换为字符型指针,并访问该指针指向的内存位置(即整型变量的第一个字节),来判断系统的字节序。如果返回的是1,说明系统的字节序是小端(因为最低有效字节存储在最低的内存地址上);如果返回的不是1,则理论上表示系统是大端。简而言之,它利用整型变量在内存中的存储方式来检测系统的字节序。

代码2

 

定义一个联合体(union),该联合体包含两个成员:一个整型(int)成员i和一个字符型(char)成员c。由于联合体的特性,这两个成员共享同一块内存空间。因此,当给整型成员i赋值时,实际上也是在修改这块共享内存的内容。

将整型成员i初始化为1(在二进制中表示为0000 0001,这里假设int类型至少占用多个字节,通常是4字节,但只关注最低有效字节)。由于整型和字符型共享内存,且字符型只占用这块内存的最低有效字节(假设是小端系统),因此字符型成员c将直接反映出整型成员i的最低有效字节的值。

然后,函数返回字符型成员c的值。如果返回的值是1,那么说明整型成员i的最低有效字节(即1)存储在最低的内存地址上,这符合小端字节序的特征。如果返回的值不是1,表示整型成员i的最低有效字节没有存储在最低的内存地址上,即系统是大端字节序。

三.练习 

练习1

 

 

charsigned char:由于它们都能存储有符号的整数值,包括-1,因此当赋值为-1时,它们能够直接存储并显示-1

unsigned char:由于它不能存储负值,当尝试将-1赋值给它时,-1被隐式转换为无符号数255(因为-1的二进制补码表示在转换为无符号数时等于255的二进制表示),因此显示结果为255

 练习2

 

char a = -128; 将负值赋给charcharsigned的。

使用printf("%u\n", a);时,a首先被提升为int(或更大整数类型),但%u要求无符号解释。

-128的二进制补码在int中表示时,高位(符号位)为1,在无符号解释下,这些位表示大数值。

因此,-128的二进制补码在无符号解释下转换为十进制数4294967168(在32位系统上)。

练习3 

 

char a = 128

使用printf("%u\n", a);时,a首先被提升为int(或更大整数类型),但%u要求无符号解释。

128的二进制补码在int中表示时,高位(符号位)为1,在无符号解释下,这些位表示大数值。

因此,128的二进制补码在无符号解释下转换为十进制数4294967168(在32位系统上)。

练习4 

 

char 类型的数组中,数字在内存中的存储:

strlen 函数找到\0后就会停止,\0的ASCII值为0,则从 -1 -2 -3 …… -128 127 126 …… 1的字符串长度是127 + 128 = 255 ,从而输出为255。

练习5 

 

 

在这道练习中,我们知道unsigned char 的范围是0到255,i<=255恒成立,则该程序死循环

 

无符号整形>=0,循环判断条件恒成立,程序死循环。

练习6 

下面我们画图来进行说明

  

后记 

共勉共勉!!!

喜欢的小伙伴点点赞,点点关注哈,谢谢各位大佬!! 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值