【C语言】数据类型的扩充和截断

(一)数据类型扩充

(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;
}
  • 结果:
    在这里插入图片描述

おすすめ

転載: blog.csdn.net/xiaoxiaoguailou/article/details/121692317