文章目录
截断定义
截断:在c语言中进行变量赋值的时候,如果将字节多的数据类型赋给字节少的数据类型时,有一部分的数据就会没有空间存储,并且只能存放低位数据,这种情况就是截断。
例如:
int i = 123;
char c = 'i';
c = i;
当进行c=i赋值操作时,会发生截断。
整型提升定义
整型提升:在c语言中整型算数运算总是至少以缺省整型类型的精度进行的,是短整型到更长整型时需要进行整型提升。
整型提升规则:
本身的数据类型无符号补0,有符号补符号位。
截断和整型提升的练习
代码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;
}
答案:a = -1, b = -1, c = 255
解析:
正常来说定义一个整型是有符号的,因此,a和b是等价的表示的范围是-128~127,c是无符号类型,表示的范围是0-255。
a的原码 10000000 00000000 00000000 00000001
a的补码 11111111 11111111 11111111 11111111
因为char类型最多表示8个位,因此从大类型到小类型会发生截断 11111111
当输出的时候,会进行补位,11111111是有符号的,并且符号位位1,因此,高位补1,结果为 11111111 11111111 11111111 11111111,这个是结果是补码的形式,再转换回去,结果为-1。b和a语句本身就是等价的,所以结果是一样的。
c的原码 10000000 00000000 00000000 00000001
c的补码 11111111 11111111 11111111 11111111
发生截断 11111111
因为是无符号类型,最高位补0,结果为 00000000 00000000 00000000 11111111 ,最终结果为255。
代码2
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n", a);
return 0;
}
答案:4,294,967,168
解析:
a这里是有符号的char类型,二进制表示为
a的原码 10000000 00000000 00000000 10000000
a的补码 11111111 11111111 11111111 10000000
截断 10000000
%u是以无符号10进制输出
整型提升 11111111 11111111 11111111 10000000
十进制 2 ^ 32 - 2 ^ 7 = 4,294,967,168
代码3
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n", a);
return 0;
}
答案:4,294,967,168
解析:
a这里是有符号的char类型,二进制表示为
a的原码 00000000 00000000 00000000 10000000
截断 10000000
%u是以无符号10进制输出
整型提升 11111111 11111111 11111111 10000000
十进制 2 ^ 32 - 2 ^ 7 = 4,294,967,168
代码4
#include <stdio.h>
int main()
{
int i = -20;
unsigned int j = 10;
printf("%d\n", i + j);
return 0;
}
答案:-10
解析:
i 这里是有符号的 int 类型,二进制表示为
i 的原码10000000 00000000 00000000 00010100
i 的补码11111111 11111111 11111111 11101100
j 这里是无符号的 int 类型,二进制表示为
j 的原码00000000 00000000 00000000 00001010
i+j等于补码11111111 11111111 11111111 11110110
原码 10000000 00000000 00000000 00001010
代码5
#include <stdio.h>
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
return 0;
}
解析:
这一串代码的运行结果是一个死循环,i是一个无符号的整型变量,当程序运行到0时,i–,输出的又是无符号的i,我们先看i=-1时的原码
原码10000000 00000000 00000000 00000001
补码11111111 11111111 11111111 11111111
输出以无符号输出,就是把这个补码看成原码,因此是个正数大于0,循环继续。