C语言中的大小端存储及原码补码反码的运算关系 %d %u

在冯诺依曼体系结构下.内存是非常重要的组成部分!

1.内存VS外存(硬盘,优盘,软盘等)

  • 1.内存支持"随机访问能力": 也就是计算机访问内存上的某个地址的数据,花费时间开销都差不多,无论地址编号的大小,时间复杂度都为O(1);外存同样也支持随机访问能力,但是支持的程度远不及内存
  • 2.内存量比较小,外存比较大
  • 3.内存访问速度快.外存慢(速度快3-4个数量级,也就是几千倍)
  • 4.内存的成本高,外存的低
  • 5.掉电后,内存的数据丢失,外存的不会丢失(电脑睡眠未掉电,关机是掉电)

2.大小端字节序存储方式问题

int NNN = 9;

端字节序: 数字的位存储早内存的地址上  (09 00 00 00 )  ----->简单记忆为: 小  小  小

端字节序: 数字的位存储在内存的地址上  (00 00 00 09)

格列佛游记中小人国讨论的问题就是: 吃鸡蛋时候,是从大头开始磕,还是从小头开始磕鸡蛋. >> 这个问题类似于大小头磕鸡蛋的问题,大端字节序存储符合人的直觉,以后可以方便记忆:吃鸡蛋从大头开始磕

3.编写一个判断机器是否小端存储的函数:

int isLittleEnd(int* p) {
	char* p2 = (char*)p;
	if (*p2 == 0x44) {
		return 1;
	}
	return 0;
}

 4.原码,反码,补码这样设计的原因在于: 计算机硬件中实现减法器,乘法器,除法器成本高,只需要在软件中通过补码运算就能解决加减乘除

减法: 加负数

乘法: 多加n次自身

除法:多减n次自身

正数的原码,反码,补码是一样的!!!

负数的存在运算关系:   补码 =  反码 + 1 ;

                                    原码  =  补码de反码 + 1;

                                    反码  =  原码除符号位取反

5.常用的%d \ %u打印实质上是什么含义?

%d 表示的是: 打印一个有符号的 十进制的整数(int型32位)

要注意的一点是: char一个字节的变量, 当按照%d打印,会将char隐式转为int型打印,转换过程中,高位的三个字节填充符号位的值.

%u 表示的是: 打印一个无符号的 十进制的整数(int型32位)

          同理.%u打印会把参数转为unsigned int类型,再进行打印

问题1: 以下代码的运行结果是:  -1 -1 255

char a = -1;
signed char b = -1;
unsigned char c  = -1;
printf( "a = %d, b = %d, c = %d", a, b, c);

char 型8位 -1 的补码是 1111 1111

int型32位   -1 的补码是 1111 1111 1111 1111 1111 1111 1111 1111

高位补的是符号位上的值,这是为了防止出现这样的转化过程中数据错误.

signed char 与 char 没有区别

unsigned char 在进行 %d打印时

1111 1111 高位补0(unsigned char 无符号位), 当做正数处理,补位按0补位.

则补位后结果是 0000 0000 0000 0000 0000 0000 1111 1111 ------> 255十进制数

结论: unsigned 类型变量比较坑, 容易在隐式转换等处发生问题, 能不用就不用unsigned.

问题2: 以下代码的运行结果是:  4,294,967,168

char a = -128;
printf("%u" ,  a);

思路: 把(char) a ---.> int----> unsigned int型打印

 高位填充符号位 1000 0000

char ---> int   \||/

1111 1111 1111 1111 1111 1111 1000 0000

int  ---> unsigned int   \||/

1111 1111 1111 1111 1111 1111 1000 0000   ||此时最高位不再是符号位, 不再表示负数,下面的数字就被理解为一个很大的正数4,294,967,168

 问题3:以下代码的运行结果是:

char a = 128; // 128溢出   char 的范围是 -128  ---> +127
printf("%u \n", a);

128内存中二进制表示的是 0000 0000 0000 0000 0000 0000 1000 0000

char a = 128;发生截断,导致唯一的1变成了符号位,此时a的值本质为 -128;

\||/ 隐式转换为int

\||/ 转换为unsigned int 变成了很大的正数(回到问题2的过程中了)

你可能感兴趣的:(C语言)