先看一段简单的代码
#include<stdio.h>
#include<stdlib.h>
int main()
{
char i=129;
printf("%d\n",i);
system("pause");
return 0;
}
大家看到肯定会有疑惑为什么输入的i为129,而以%d打印出来却是-127?这其中就涉及到截断和整形提升。
首先我们都知道一个char类型的常量在内存中所占的是一个字节的长度,即8个bit位。
而一个十进制的129是一个整形,在内存中占四个字节,32个bit 位,而 i 中只能保存一个字节即8个bit 位的二进制位。
我们都知道129的二进制位为:
00000000 00000000 00000000 10000001
当强行把 int 类型的赋给 char 类型时就会发生截断。如这段代码中的 i 就会截取 129的32 位二进制中的低8位,即
10000001
而打印时却需要以%d 的形式打印出来这就涉及到整形提升。
而现在只有八位 00000001 如何提升到整形的32位呢?
这里有两种情况,先来看一段代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
char i=129;
signed char j=129;
unsigned char k=129;
printf("%d\n",i);
printf("%d\n",j);
printf("%d\n",k);
system("pause");
return 0;
}
有符号:
当为有符号时截断的左边第一位为符号位,如果为 1 前24位全部补1,如果全部为 0 前24位全部补0。
本题是10000001所以全部补1即为
11111111 11111111 11111111 10000001
在这里就有人疑问这里不是-129吗?怎么打印结果是-127?
因为是有符号所以这里复习一下整数在电脑中是如何存储的
都是以补码形式存储
正数:原反补都相同
负数:原码:也就是二进制的翻译 。 反码:除符号位其余的二进制位全部取反。 补码:反码+1。
则它的补码为
10000000 00000000 00000000 01111111
打印出来即为:-127
无符号:
可以看到当为 unsigned 无符号的时候时是129。这是因为在截断了8个bit 位时把它当成了一个无符号位的二进制,前24位统一补0;
因此得到二进制为
00000000 00000000 00000000 10000001
即为129。