1. 整数在内存中的存储 : 整数的2进制表⽰⽅法有三种,即 原码、反码和补码 有符号的整数,三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表 ⽰“负”,最⾼位的⼀位是被当做符号位,剩余的都是数值位。 正整数的原、反、补码都相同。 负整数的三种表⽰⽅法各不相同。 原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。 反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。 补码:反码+1就得到补码。 为什么数据在内存中是以二进制补码形式存放的呢? 在计算机系统中,数值⼀律⽤补码来表⽰和存储。 原因在于,使⽤补码,可以将符号位和数值域统⼀处理; 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是 相同的,不需要额外的硬件电路。 2.大小端字节序存储 ⼤端(存储)模式: 是指数据的低位字节内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存在内存的低地址处。 ⼩端(存储)模式: 是指数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存在内存的⾼地址处 为什么会有⼤⼩端模式之分呢? 这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为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处理器还可以由硬件来选择是 ⼤端模式还是⼩端模式。 练习:写一个程序判断当前机器是大端字节序还是小端字节序 这里要把a的地址转化为char*类型,这样才能保证解引用操作时一次访问一个字节。
接下来通过几道经典题目加深对本节知识的理解:
题目一:
本题目主要考察指针加减整数的运算以及大小端字节序存储的相关知识。
解析:a是数组名,数组名表示数组首元素的 地址(两种情况例外:sizeof(数组名),&数组名)
&表示取出整个数组的地址(类型是int(*)【4】)加一跳过整个数组(指针类型决定了+-整数的步长)再将数组指针变量强制转化为int*型,-1(ptr[-1]等价于*(ptr-1))跳过4个字节(一个整型)解引用得到4。
a是数组名,数组名表示数组首元素的 地址,将a(地址)强转为int类型再加1,在换算成整型指针(地址)
+1跳过了一个字节,再进行解引用操作访问4个字节,具体如下图所示:
由于是小端字节序存储,所以解引用操作后在内存中存储的00 00 00 02会被还原读取出来
因此得到20 00 00 00(16进制表示形式)
题目二:下图程序的运行结果是?
本题目答案为死循环。
解析:char类型数据的存储范围是-128~127
00000000————0
00000001————1
00000010————2
………………
01111111————127
10000000————直接翻译成-128
10000001———— -127(转换为源码再算)
11111111———— -1
unsigned char类型的数据存储范围为0~255————11111111(2^8-1)
11111111在加一变为100000000,unsigned char类型只能保留8个bit位,首位的一会丢失,所以i达到255后在加一又会回到0,循环往复。
因此i<=255是恒成立的,程序会陷入死循环。
题目三:下图程序的运行结果是?
由上图不难看出,程序陷入了死循环。
解析:unsigned int类型的数据存储范围为0~2^32-1,当i减为0时在减一i就会变成2^32-1,循环往复。因此本题目i>=0是恒成立的,所以会陷入死循环。(0-1=-1,32位全一,全是数值位)
题目四:
解析:strlen的任务是找到字符数组中的\0,返回\0之前的元素个数。
char类型的数据存储范围为-128~127
所以数组a的内容如下:
-1 | -2 | -3 | …… | -128 | 127 | …… | 3 | 2 | 1 | 0 | 0 | 0 | 0 |
因此本题结果为128+127=255.
题目五:
解析:%u打印无符号整数,a是一个char型数据,128在内存中的存储形式为
00000000 00000000 00000000 10000000
char只保留一个字节 10000000
%u打印无符号整数,整形提升补符号位
11111111 11111111 11111111 10000000
由于%u打印无符号的整数,因此系统会认为上面的数字就是原码。转换成10进制就是4294967168
题目六:
本题目 -128
10000000 00000000 00000000 10000000————原码
11111111 11111111 11111111 01111111————反码
11111111 11111111 11111111 10000000————补码
char只保留一个字节 10000000
整型提升11111111 11111111 11111111 10000000
由于%u打印无符号的整数,因此系统会认为上面的数字就是原码。转换成10进制就是4294967168
题目七:
解析:
-1
10000000 00000000 00000000 00000001————原码
11111111 11111111 11111111 11111110————反码
11111111 11111111 11111111 11111111————补码
char只保留一个字节11111111
以%d形式打印,需要整形提升,补符号位
11111111 11111111 11111111 11111111
再翻译成原码,10000000 00000000 00000000 00000001,因此打印-1.
但由于c的类型是unsigned char,是无符号的,因此其在整形提升时补0
00000000 00000000 00000000 11111111
无符号整数的原反补相同,因此直接翻译255(2^8-1).
完
标签:11111111,存储,10000000,字节,00000000,char,内存,数据,原码 From: https://blog.csdn.net/2403_88695928/article/details/143770942