C语言中 unsigned char 与 signed char 不同输出格式一些认识

首先考虑下面代码输出什么?


#include <stdio.h>

 

int main(void)

{

 

	signed char a = -1;

	unsigned char b = -1;

 

	printf("%%d:\n");

	printf("%d\n", a);

	printf("%d\n", b);

 

	printf("\n%%u:\n");

	printf("%u\n", a);

	printf("%u\n", b);

 

	return 0;

		

}	

%d格式下 a = -1 b = 255,%u格式下 a = 4294967295 b = 255.

下面我们进行分析为什么会出现这种结果:

首先数字在内存中以他的补码形式保存, -1的补码为全1,这个不会因为他被赋予变量大小或变量类型有无符号而改变。变量大小改变的是存储此数字的位数,例如signed char 变量 -1补码存储在它里面为 11111111(1字节。) signed int 为 11111111 11111111 11111111 11111111(假设此时int为4字节)。变量类型有无符号表示如何看待最高位。
例如 -1 赋予一个 signed char变量 。 则11111111最高位1被当为符号位。 -1被赋予一个unsigned char变量 则11111111 最高位1被当作数值位(不再当作符号位)。

此时我们来分析 signed char -1 以%d 形式输出。 首先它以补码形式存储在此类型变量, 11111111 最高位被当作符号位。 因为要求以%d(十进制有符号整数类型)输出。
因此我们将他的补码补到32位。 因为他为signed 类型,所以补码补符号位。 11111111前面补24个符号位1即补码变为FFFFFFFF。 又因为以十进制有符号整数类型格式输出(将这个FFFFFFFF看作一个有符号数补码,将这个补码以%d格式进行解释,并输出),所以把最高位看为符号位,即他为一个负数。 将此负数补码转换为原码可得 10000000 00000000
00000000 00000001所以输出-1.
同理分析%u 形式输出。 补完符号位后补码变为FFFFFFFF。 此时以无符号十进制整数形式输出(即把这个FFFFFFFF看做一个无符号数的补码), 我们将他最高位看做数值位,无符号数即大于等于0数。 所以原码即补码 ,所以源码为FFFFFFFF的二进制数值为4294967295.

接下来分析 unsigned char -1. -1以补码形式存储在内存中的值为全1。 将他赋给一个unsigned char变量时, 为 11111111(依然是这种形式不变)。只是系统认为他的最高位不是符号位,为数值位。 此时以%d 格式输出,先进行补码补全。 因为此时为unsigned 所以 11111111前面补数字0而不是符号位. 补全后补码变为
00000000 00000000 00000000 11111111 此时以%d 格式打印。 最高位为0,系统把他看做一个正数的补码, 即原码也是这个。 此原码值为255.

最后,以%u形式输出(系统认为此补码代表一个大于等于0数,所以即使最高位为1,也被当作数值位。而不是把他当作负数)。 00000000 00000000 00000000 11111111 %u格式把最高位当作数值位。 值为255.

此代码可判断你的编译器char是什么类型,加上一条 char c = -1; 判断a.b.c输出值即可。

下面代码是另一种问题:


#include <stdio.h>

 

int main(void)

{

 

	signed char a = 128;

	signed char b = -128;

 

	printf("%%d:\n");

	printf("%d\n", a);

	printf("%d\n", b);

 

	printf("\n%%u:\n");

	printf("%u\n", a);

	printf("%u\n", b);

 

	return 0;

		

}	

我们先进行分析,char变量为一个字节,八比特位。存储有符号数时最高位为符号位。 而128二进制形式为10000000.
有符号数128 最高位 为 0 后八位为10000000 存储在signed char变量中,因为此变量只有八个比特位空间, 所以存储时被截断为 10000000.
此时,因为为signed char类型,最高位1被解释为符号位。
以%d形式输出,先补全补码,补符号位1. 11111111 11111111 11111111 10000000. 随后,%d格式,所以他被解释为一个负数的补码,转化为原码,数值为-128.
%u格式易得值为.

signed char -128.最高位为1 后八位为100000000。 存储时被截断为10000000. 同理可分析,%d%u格式与128输出相同.
————————————————
版权声明:本文为CSDN博主「ssopp24」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ssopp24/article/details/52838210

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值