一、整形计算机表示及内存中的存储
1.整形计算机表示
数值有不同的表示形式——2进制【0b开头】、8进制【0开头】、10进制【没有前缀】、16进制【0x开头】等。
2进制序列写成16进制序列 时,4个比特位和为一个【分别对应2的0、1、2、3次方】,每两个放到一块,前边再加上0x
内存中本质还是2,但是为了我们分析/编译器显示方便,一般会表示16进制。
整数的二进制的三种表示形式:
原码:直接通过正负的形式写出的二进制序列就是原码
反:原码符号位不变,其他位按位取反得到的就是反码
补:反码+1
另外:原码除了可以通过补码产生的逆运算得到,也可以由补码+1,在按位取反(符号位除外)得到。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位表示各不相同。
正整数
正整数原反补相同
负整数
写出原码,根据计算规则算出反码补码。
2. 整形内存表示——补码
对于整形,计算机存放的其实是补码的二进制序列。
原因
在计算机系统中,数值一律用补码来表示和存储。
原因
使用补码,可以将符号位和数值域统一处理;-----1
同时,加法和减法也可以统一处理(CPU****只有加法器)-----2
此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。-----3
二、大小端字节序详解
我们已经知道整数在计算机内部统统存的都是补码,但是我们可以看到他们显示的顺序好像跟我们以为的补码不太一样,这里就涉及到了大小端字节序的问题。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zPByoo4F-1657982303258)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715142543310.png)]](https://img-blog.csdnimg.cn/03fc857501ab482b9be9d25d7aca64cc.png)
1. 什么是大小端字节序
大端(存储):数据低位存储在内存的高地址、数据高位存储在内存的低地址。
小端(存储):数据高位存储在内存的高地址、数据低位存储在内存的低地址。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-npuTNjzc-1657982340352)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715142900324.png)]
2.为什么会有大小端字节序之分
在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8 bit。
但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编译器)
另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
简言之,只要超过两个字节以上就有顺序问题,char、double等都有——内存存储问题。
但是存储顺序——五花八门,其他的太麻烦,正放反放两种比较方便。
【画图时无特殊要求时,低地址到高地址是根据自己习惯决定的】
补充
大端存储和小端存储都取决于硬件,市面上大部分都是小端存储,这些跟编译器没有什么关系
例如,x86结构就是小端模式
3.一道真题
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kDMOzDEv-1657982303261)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715143941474.png)]](https://img-blog.csdnimg.cn/f6cbe47801a74fbdb82cf574f2f2198d.png)
所以我们只要拿到它的第一个字节存储的值看是0还是1,就可以判断。——这里体现了指针类型的意义。
所以,答案可以为
#include <stdio.h>
int check_sys()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = check_sys();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
补充:【&a,是地址编号,本质上是一个整形】——所以打印的时候可以以%d形式打印。
4.练习题
1)该段程序输出什么?
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Som7O7eL-1657982303262)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716192549764.png)]](https://img-blog.csdnimg.cn/1e0103e49cb54791b2db9b9f97d4b8c5.png)

2)下面程序输出什么?
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hq9MZyk7-1657982303263)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716192409545.png)]](https://img-blog.csdnimg.cn/88b3cfd56ab1422c97d1f2456b4f50f3.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VKwAFEyj-1657982303265)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716190524817.png)]](https://img-blog.csdnimg.cn/5316155a3171446ca4d996e1f89001cf.png)
3)下面程序输出什么?
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
 
4)
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2PJIman-1657982303267)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716202416312.png)]](https://img-blog.csdnimg.cn/f6259bc156f34c8ab4b9c09cdb526191.png)

5)
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xL2D5AuS-1657982303268)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716203536552.png)]](https://img-blog.csdnimg.cn/6c46d114c1c54f2597fed08073e63821.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BgHdou9c-1657982303269)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716202652015.png)]](https://img-blog.csdnimg.cn/8dab8041fe8d438db9fa6f5f13a3e542.png)
6)
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cEzoKWoL-1657982303270)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716205114003.png)]](https://img-blog.csdnimg.cn/281704d770c040258e74e024ee3cbd55.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0sxKdUCy-1657982303271)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716205130467.png)]](https://img-blog.csdnimg.cn/e5208e57a21c4a1e980b3e1f03c7522b.png)
7)
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lgrgJWbl-1657982303272)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716211221910.png)]](https://img-blog.csdnimg.cn/0d65693bf9384047a5bf05c9e4e6de5b.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EiscByoU-1657982303273)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716211201446.png)]](https://img-blog.csdnimg.cn/20d79de9a4384746b24f26776f3304a8.png)
三、重点强调
1.整数内存存储形式——补码
2.整数运算——补码,原码/其他形式打印
3.特别小心无符号数,同时小心strlen的返回值。
4.截断的方法——从补码的低位开始,整型提升方法——复习操作符之整形提升算数转换那块。
5.大小端字节序存储这块知识多与指针练习题紧密结合,特别小心。
|