您的位置:首页 > 编程语言 > C语言/C++

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

2016-10-17 13:53 246 查看
首先考虑下面代码输出什么?

#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输出相同.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息