隐式类型转换

目录

 

前言

一、赋值转换

二、运算转换

2.1 - 整型提升


 


前言

在 C 语言中,类型转换的方式一般可分为隐式类型转换显示类型转换(也称为强制类型转换)。其中隐式类型转换由编译器自动进行,不需要程序员干预。

隐式类型转换通常有两种情况:赋值转换运算转换

 

一、赋值转换

将一种类型的数据赋值给另外一种类型的变量时,发生隐式类型转换。例如:

double pi = 3.14;
int num = pi;

在对变量赋值时,若等号两边的数据类型不同,需要把右边表达式的类型转换为左边变量的类型,这可能导致数据失真(精度降低),所以隐式类型转换不一定安全。  

 

二、运算转换

C 语言中不同类型的数据需要转换成同一类型,才可以计算。转换规则如下:

  • 转换按照数据长度增加的方向进行,以保证精度不降低。比如 int 类型的数据和 double 类型的数据相加时,int 类型的数据就会被隐式地转换成 double 类型,然后再进行运算。

  • 如果两种类型的字节数一样,且一种有符号,另一种无符号,则转换成无符号类型

  • char 类型和 short 类型参与运算时,必须先转换成 int 类型(整型提升)

示例

#include <stdio.h>

int main()
{
	int num = -1;
	printf("%d\n", sizeof(num));  // 4
	if (num < sizeof(num))
		printf("num < sizeof(num)\n");
	else
		printf("num >= sizeof(num)\n");
	return 0;
}

输出结果:num >= sizeof(num),这是因为 num 的类型是 int,而 sizeof(num) 的返回值类型是 unsigned int,因此在比较运算中,num 被隐式地转换成了 unsigned int。

 

2.1 - 整型提升

整型提升(integral promotion)是 C 程序设计语言中的一项规定:在表达式计算时,各种整型首先要提升为 int 类型,如果 int 类型不足以表示,则要提升为 unsigned int 类型,然后执行表达式的运算。例如,C 语言标准中仅规定了 char 的长度 <= short 的长度 <= int 的长度,这意味着在 short 与 int 的长度相等的情况下,unsigned short 就无法提升为 int,只能提升为 unsigned int。

整型提升的意义:表达式的整型运算要在 CPU 的相应运算器件内执行,CPU 内整型运算器(ALU)的操作数的字节长度一般就是 int 的字节长度,同时也是 CPU 的通用寄存器的长度。因此,即使两个 char 类型的相加,在 CPU 执行时实际上也要先转换为 CPU 内整型操作数的标准长度。通用 CPU(general-purpose CPU)是难以直接实现两个 8 比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度小于 int 长度的整型值,都必须先转换为 int 或 unsigned int,然后才能送去 CPU 去执行运算

注意:整型提升是有符号补符号位,无符号则补 0

示例一

#include <stdio.h>

int main()
{
	char a = 3;
	// 00000000 00000000 00000000 00000011(3 的补码)
	// 截断:
	// 00000011(a 的补码)
	char b = 127;
	// 00000000 00000000 00000000 01111111(127 的补码)
	// 截断:
	// 01111111(b 的补码)
	char c = a + b;
	// 表达式计算时,需要进行整型提升,即:
	// 00000000 00000000 00000000 00000011
	// +
	// 00000000 00000000 00000000 01111111 
	// =
	// 00000000 00000000 00000000 10000010
	// 截断:
	// 10000010(c 的补码)
	printf("%d\n", c);
	// %d 是 int 类型数据的占位符,因此要进行提升,即:
	// 11111111 11111111 11111111 10000010
	// 10000000 00000000 00000000 01111110(原码 ==> -126)
	return 0;
}

示例二

#include <stdio.h>

int main()
{
	char a = 0xb6;  
	short b = 0xb600;
	int c = 0xb6000000;
	if (a == 0xb6)
		printf("a\n");
	if (b == 0xb600)
		printf("b\n");
	if (c == 0xb6000000)
		printf("c\n");
	// char 类型的变量 a 和 short 类型的变量 b 在参与表达式计算时被提升为 int 类型,分别为:
	// 11111111 11111111 11111111 10110110,即 0xffffffb6
	// 11111111 11111111 10110110 00000000,即 0xffffb600
	// int 类型的变量 c 没有进行整型提升,因此输出的结果是 c。
	if (a == 0xffffffb6)
		printf("hehe\n");
	if (b == 0xffffb600)
		printf("haha\n");
	// 输出 hehe 和 haha
	return 0;
}

示例三

#include <stdio.h>

int main()
{
	char a = 1;
	printf("%zd\n", sizeof(a));  // 1
	printf("%zd\n", sizeof(+a));  // 4
	printf("%zd\n", sizeof(-a));  // 4
	// char 类型的变量 a 作为 +/- 的操作数参与运算时,需要进行整型提升
	return 0;
}

 

隐式类型转换,也称为自动类型转换,是在 C++ 编程中的一种自动转换机制,它发生在当一种类型的值被赋给另一种类型的变量时,或者是作为函数参数传递时,目标类型能够自动推导出源类型的情况。这种转换通常是编译器进行的优化处理,旨在简化代码编写,并尽量减少显式转换的需要。隐式转换遵循一些特定的规则和优先顺序,以保证程序的正确性和一致性。 ### 隐式类型转换的主要特点包括: 1. **大小一致的转换**:如果目标类型比原始类型大,则会从较小类型自动转换到较大类型。例如,从 `char` 到 `int` 的转换就是隐式的。 2. **窄化(截断)**:从较大的类型转换到较小的类型时,可能发生信息丢失的情况,此时被称为“窄化”。例如,从 `long long` 转换为 `short` 将丢失精度。 3. **强制类型转换**:有时候虽然隐式转换是合法的,但为了保持代码的明确性和可读性,程序员可以选择使用 `(类型)表达式` 来进行显式转换。 ### 常见的例子: - **整数间的隐式转换**: ```cpp char ch = 'A'; // 字符常量 int i = ch; // 自动转换为整数 ``` - **浮点数和整数之间的转换**: ```cpp float f = 5.6f; // 浮点数 int i = (int)f; // 显式转换为整数,保留小数部分的信息 ``` - **自动数组初始化**: ```cpp int a = {1}; // 初始化为{1, 0, 0} ``` 在此例中,最后一个元素默认填充零,这是一种隐式行为。 ### 注意事项: - **窄化损失**:在进行窄化转换时,一定要注意是否有信息丢失的风险,特别是涉及数学运算时(比如浮点数转整数)。 - **性能考虑**:过多的隐式转换可能导致编译器生成更复杂的机器码,进而影响程序性能。 - **代码可读性**:尽管隐式转换可以提高代码的简洁度,但过度依赖隐式转换也可能降低代码的可读性和可维护性,尤其是在大型项目中。 理解隐式类型转换有助于编写更高效、更容易维护的 C++ 程序。掌握其工作原理及潜在风险对于成为一个熟练的 C++ 开发人员至关重要。如果你对其他方面感兴趣,欢迎提问!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值