文章目录
(一)数据类型扩充
(1)表示范围小的整型变量赋值给表示范围大的整型变量
前提:
- 不改变值的正负
- 不改变值的大小
规则:
- 无符号整数,直接补0。
- 有符号整数,扩充符号位。
- 与左值的有无符号无关(例:
short x = a; 与x是否有符号无关
)
(二)数据的截取(切片)
(1)将数据类型较大的变量赋给数据类型较小的变量
- 规则:无论有无符号,丢弃
高位
数据
(三)算术类型转换和赋值类型转换
- 自动类型转换:隐式类型转换
- 强制类型转换:显示类型转换
类型相容:
- 类型不同,但系统(编译器在编译阶段)可以自动类型转换(低精度——>高精度,小范围——>大范围),只针对
基本数据类型
- 基本数据类型:char、short、 int、long、long int、long long、unsigned char、unsigned short、unsigned int、 unsigned long int、unsigned long long,float、double类型
- 特定类型:指针、数组、结构体类型(不支持强转)、联合体类型、枚举类型不适用
(1)类型运算、转换规则
例(1)
#include <stdio.h>
int main()
{
char a = -5;
unsigned int b = 10;
if (a > b)
{
printf("%d > %d\n", a, b);
//无符号输出
printf("%u > %u\n", a, b);
}
else
{
printf("%d < %d\n", a, b);
}
return 0;
}
分析:
- a和b进行比较时,signed char类型的a会自动转换成 unsigned int类型
- a = -5对应一字节补码
1111 1011
, 将补码扩充到4字节,对应的补码就是1111 1111 1111 1111 1111 1111 1111 1011
- 再将扩充后的补码
1111 1111 1111 1111 1111 1111 1111 1011
解析成无符号类型(正数),对应的原码就是1111 1111 1111 1111 1111 1111 1111 1011
对应的十进制 远远大于10
结果:
例(2)
#include <stdio.h>
int main()
{
char a = -5; //int 4字节补码1111 1111 1111 1111 1111 1111 1111 1011(-5)
unsigned short b = 10; //int 4字节补码0000 0000 0000 0000 0000 0000 0000 1010(10)
//char 和short都转成int 类型
if (a > b)
{
printf("%d > %d\n", a, b);
//无符号输出
printf("%u > %u\n", a, b);
}
else
{
printf("%d > %d\n", a, b);
}
return 0;
}
分析:
当char类型和short类型进行转化时,都会转成signed int类型
char a = -5; //int 4字节补码1111 1111 1111 1111 1111 1111 1111 1011(-5)
unsigned short b = 10; //int 4字节补码0000 0000 0000 0000 0000 0000 0000 1010(10)
结果:
例(3)
#include <stdio.h>
int main()
{
/*
分析:
sizeof(int)== 4的值是一个unsigned int类型
比较时,signed int 会转成 unsigned int类型
-3补码:1111 1111 1111 1111 1111 1111 1111 1101
4补码:0000 0000 0000 0000 0000 0000 0100
以无符号来解读1111 1111 1111 1111 1111 1111 1111 1101就是很大的数 > 4
所以不进入循环
*/
for (int i = -3; i < sizeof(int); i++)
{
printf("%d ", i);
}`在这里插入代码片`
return 0;
}
- 结果:
例(4)肥肠重要!!!!!!!!
#include <stdio.h>
int main()
{
char a = 100;
char b = 200;
char c = a + b;
/* 有符号
100: 0110 0100
-56: 1100 1000
c = 44: 1 0010 1100(截取低地址8位)
%d输出表示再对c进行int类型扩充:
0000 0000 0000 0000 0000 0000 0010 1100(44)
*/
//%d格式符代表以有符号整型输出 a + b
/*
分别将char的a、b扩充成int,在对其补码进行运算
a`: 0000 0000 0000 0000 0000 0000 0110 0100
b`: 1111 1111 1111 1111 1111 1111 1100 1000
1 0000 0000 0000 0000 0000 0000 0010 1100(截取低地址32位)
结果:`a + `b = 44
*/
printf("c = %d, a + b = %d\n", c, a + b);
unsigned char ua = 100;
unsigned char ub = 200;
unsigned char uc = ua + ub;
/*无符号
100: 0110 0100
200: 1100 1000
uc:1 0010 1100(截取低地址8位)
以%d输出uc
0000 0000 0000 0000 0000 0000 0010 1100(44)
-------------------------------------------
以%d输出 ua + ub
先将ua、ub扩充成int
ua`: 0000 0000 0000 0000 0000 0000 0110 0100
ub`: 0000 0000 0000 0000 0000 0000 1100 1000
ua` + ub`:
0000 0000 0000 0000 0000 0001 0010 1100(300)
*/
printf("uc = %d, ua + ub = %d\n", uc, ua + ub);
return 0;
}
- 结果:
例(5)肥肥非常重要!!!!!!!!!
#include <stdio.h>
int main()
{
char c = 128;
unsigned char uc = 128;
unsigned short usum = 0;
/*
有符号c: 1000 0000(魔鬼数-128)
无符号uc: 1000 0000
无符号short usum:
扩充后:
c: 1111 1111 1000 0000
uc:0000 0000 1000 0000
补码运算:1 0000 0000 0000 0000(取低地址16位)->0
*/
usum = c + uc;
printf("%x\n", usum);
/*
有符号c: 1000 0000(魔鬼数-128)
无符号uc: 1000 0000
强转无符号c: 1000 0000
无符号uc: 1000 0000
无符号char usum:
扩充:
c: 0000 0000 1000 0000
uc:0000 0000 1000 0000
补码运算:0000 0001 0000 0000(取地址16位)->(0x100)
*/
usum = (unsigned char)c + uc;
printf("%x\n", usum);
/*
有符号c: 1000 0000(魔鬼数-128)
无符号uc: 1000 0000
uc强制转成有符号:1000 0000
c和uc再转成unsigned short
c: 1111 1111 1000 0000
uc:1111 1111 1000 0000
补码运算: 1 1111 1111 0000 0000(取低地址16位0xff00)
*/
usum = c + (char)uc;
printf("%x\n", usum);
/*
有符号c: 1000 0000(魔鬼数-128)
无符号uc: 1000 0000
c扩充无符号short
c: 1111 1111 1000 0000
uc扩充成无符号short
uc: 0000 0000 1000 0000
补码运算:
1 0000 0000 0000 0000(取低地址16位 0x00)
*/
usum = (unsigned short)c + uc;
printf("%x\n", usum);
return 0;
}
- 结果: