当前位置: 首页 > news >正文

【C/C++】具有C风格的强制类型转换:显式类型转换、隐式类型转换,C语言强制类型转换


🔥个人主页:艾莉丝努力练剑

专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、C/C++干货分享&学习过程记录

🍉学习方向:C/C++方向

⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平


前言:本专栏记录了博主C++从初阶到高阶完整的学习历程,会发布一些博主学习的感悟、碰到的问题、重要的知识点,和大家一起探索C++这门程序语言的奥秘。这个专栏将记录博主C++语法、高阶数据结构、STL的学习过程,正所谓“万丈高楼平地起”嘛,我们话不多说,继续进行C++阶段的学习。本文我们不讲C++主线的内容,我们来拓展一下或者说整理一下我们学习时C/C++时经常会提到的一些专有名词,例如形参、实参,显式类型转换和隐式类型转换类型转换,内置类型等等。


 


C++的两个参考文档:

老朋友(非官方文档):cplusplus

官方文档(同步更新):cppreference


目录

正文

具有C风格的强制类型转换:式类型转换、隐式类型转换

一、隐式类型转换 (Implicit Type Conversion)

常见场景:

转换规则:

算术转换 (Arithmetic Conversion):

整数提升 (Integer Promotion):

二、显式类型转换 (Explicit Type Conversion)

C 风格强制转换语法:

三、C++ 中的改进(对比)

实践

详解显式类型转换与隐式类型转换

一、隐式类型转换

1、常见的隐式类型转换场景

(1) 算术转换 (Arithmetic Conversion)

(2) 赋值转换 (Assignment Conversion)

(3) 函数调用转换 (Function Call Conversion)

(4) 返回类型转换 (Return Conversion)

2、隐式转换的规则体系

(1) 整数提升 (Integer Promotion)

(2) 寻常算术转换 (Usual Arithmetic Conversion)

(3) 有符号与无符号转换

3、隐式转换的风险

二、显式类型转换 

1、C风格的显式转换

(1) 基本类型转换

(2) 指针类型转换

(3) 函数指针转换

2、C++风格的显式转换

(1) static_cast

(2) const_cast

(3) dynamic_cast

(4) reinterpret_cast

3、显式转换的风险示例

(1) 数据截断

(2) 指针误用

(3) 类型双关 (Type Punning)

三、实践方面的建议

四、典型面试问题

结尾


正文

在C语言中,类型转换分为显式类型转换和隐式类型转换两种方式。C++ 也支持这些 C 风格的转换,但推荐使用更安全的 C++ 风格类型转换操作符。

具有C风格的强制类型转换:式类型转换、隐式类型转换

一、隐式类型转换 (Implicit Type Conversion)

隐式类型转换,又称自动类型转换,是编译器在不需要程序员显式指定的情况下自动进行的类型转换。

常见场景:

  • 赋值时类型不匹配

  • 表达式中有不同类型的操作数

  • 函数调用时实参与形参类型不匹配

int i = 42;
double d = i;  // 隐式将int转换为doublefloat f = 3.14f;
double sum = f + d;  // 隐式将f提升为doublevoid func(double x);
func(i);  // 隐式将int转换为double

转换规则:

算术转换 (Arithmetic Conversion):

1、小类型向大类型转换;

2、整型向浮点型转换;

3、有符号向无符号转换(可能导致意外结果)。

整数提升 (Integer Promotion):

1、charshort 等小整型在运算时自动提升为 int。

二、显式类型转换 (Explicit Type Conversion)

使用强制类型转换运算符显式指定转换。

C 风格强制转换语法:

(type_name) expression
// 或
type_name (expression)  // C++ 中可用

我们举个例子:

double d = 3.14159;
int i = (int)d;  // 显式将double转换为int,截断小数部分float f = 1.5f;
int j = int(f);  // C++风格的写法,效果相同unsigned int u = 0xffffffff;
int k = (int)u;  // 可能产生负数

注意:

1、强制转换会绕过编译器的类型检查;

2、可能导致数据丢失或未定义行为;

3、指针类型转换非常危险。

int x = 10;
char *p = (char *)&x;  // 危险:可能违反严格别名规则

三、C++ 中的改进(对比)

C++ 提供了四种更安全的类型转换操作符:

1、static_cast —— 用于良性转换

2、const_cast —— 去除 const 属性

3、dynamic_cast —— 用于多态类型的向下转换

4、reinterpret_cast —— 低层重新解释(最危险)

double d = 3.14;
int i = static_cast<int>(d);  // C++推荐方式

实践

  1. 尽量避免使用 C 风格的强制转换;

  2. 优先使用隐式转换(当安全时);

  3. 必须显式转换时,C++ 中优先使用 static_cast 等新式转换;

  4. 特别注意指针和整型之间的转换;

  5. 注意有符号和无符号类型之间的转换陷阱。

详解显式类型转换与隐式类型转换

一、隐式类型转换

隐式类型转换又称自动类型转换,是编译器在不需要程序员显式指定的情况下自动进行的类型转换。

1、常见的隐式类型转换场景

(1) 算术转换 (Arithmetic Conversion)

当表达式中包含不同类型的操作数时发生:

int i = 5;
double d = 2.5;
double result = i + d;  // i被隐式转换为double
(2) 赋值转换 (Assignment Conversion)

当赋值运算符两侧类型不一致时:

int i;
double d = 3.14;
i = d;  // d被隐式转换为int,小数部分被截断
(3) 函数调用转换 (Function Call Conversion)

实参与形参类型不匹配时:

void func(double x);
func(5);  // int 5被隐式转换为double 5.0
(4) 返回类型转换 (Return Conversion)

返回类型与函数声明类型不一致时:

double func() 
{return 5;  // int 5被隐式转换为double 5.0
}

2、隐式转换的规则体系

(1) 整数提升 (Integer Promotion)
  • charshort等小整型自动提升为int

char c1 = 'A', c2 = 'B';
int result = c1 + c2;  // char提升为int再相加
(2) 寻常算术转换 (Usual Arithmetic Conversion)

按以下优先级转换(低→高):

  1. boolcharshort → int

  2. int → unsigned int

  3. unsigned int → long

  4. long → unsigned long

  5. unsigned long → long long

  6. long long → unsigned long long

  7. 整型 → float

  8. float → double

  9. double → long double

(3) 有符号与无符号转换
unsigned int u = 10;
int i = -5;
if (i < u) 
{  // i被转换为unsigned int,结果可能出乎意料// 这里可能不会执行
}

3、隐式转换的风险

int i = 300;
char c = i;  // 可能溢出,结果依赖于实现

二、显式类型转换 

显式类型转换是程序员明确指定的类型转换,也称为强制类型转换。

1、C风格的显式转换

语法:

(type_name) expression
// 或
type_name (expression)  // C++风格
(1) 基本类型转换
double d = 3.14159;
int i = (int)d;  // 截断小数部分,i=3
(2) 指针类型转换
int x = 10;
char *p = (char *)&x;  // 重新解释内存
(3) 函数指针转换
void (*func_ptr)() = (void (*)())some_function;

2、C++风格的显式转换

C++提供了四种更安全的转换操作符——

(1) static_cast

用于良性转换,编译时检查:

double d = 3.14;
int i = static_cast<int>(d);
(2) const_cast

移除const/volatile属性:

const int ci = 10;
int *pi = const_cast<int*>(&ci);
(3) dynamic_cast

用于多态类型的安全向下转换:

Base* b = new Derived();
Derived* d = dynamic_cast<Derived*>(b);
(4) reinterpret_cast

低层重新解释,最危险:

int i = 10;
float f = reinterpret_cast<float&>(i);

3、显式转换的风险示例

(1) 数据截断
double d = 3.9;
int i = (int)d;  // i=3,小数部分丢失
(2) 指针误用
int x = 0x12345678;
char *p = (char *)&x;
if (*p == 0x78) 
{  // 依赖于字节序// 在小端机器上成立
}
(3) 类型双关 (Type Punning)
float f = 3.14f;
unsigned u = *(unsigned *)&f;  // 违反严格别名规则

三、实践方面的建议

  1. 优先使用隐式转换:当转换安全且意图明显时

  2. 慎用显式转换:特别是指针和引用类型的转换

  3. C++推荐使用新式转换:比C风格转换更安全

  4. 注意数值范围:确保目标类型能容纳转换后的值

  5. 避免类型双关:使用union或memcpy替代危险指针转换

  6. 使用static_assert检查:C++11起可用

static_assert(sizeof(int) == 4, "int must be 4 bytes");

四、典型面试问题

1、以下代码的输出是什么?

unsigned int u = 10;
int i = -5;
if (i < u) 
{printf("True");
} 
else 
{printf("False");
}

答案:可能输出"False"(因 i 被转换为很大的unsigned值)。

2、如何安全地将float的位模式转换为int?

float f = 3.14f;
int i;
memcpy(&i, &f, sizeof(f));  // 安全方式

结尾

往期回顾:

由于往期回顾的博客太多了,这里就只放前一篇博客的链接啦——

【C/C++】深入详解内置类型和自定义类型

关于C++的四种强制转换类型,大家可以去看这位大佬的博客,比较易懂——

【C++】深度解析C++的四种强制转换类型(小白一看就懂!!)

往期回顾(本文涉及的一些往期博客)

C风格的强制类型转换:

【C/C++】初识C++(三):C++入门内容收尾——const引用,指针和引用关系梳理,inline(内联函数),nullptr替代NULL

C语言中的强制类型转换:

变量的一些知识点整理(续)、算术操作符、赋值操作符:=和复合赋值、单目操作符以及强制类型转换的知识点总结

结语:本文内容到这里就全部结束了。本文博主带大家回顾了介绍C语言时就登场,一直到现在都有不少戏份的强制类型转换,C++中具有C风格的强制类型转换:显式类型转换、隐式类型转换。

http://www.dtcms.com/a/323397.html

相关文章:

  • 第六章:【springboot】框架springboot原理、springboot父子工程与Swagger
  • 算法题(183):质量检测
  • 《答客难》东方朔
  • 网络原理-初识
  • FreeRTOS入门知识(初识RTOS任务调度)(三)
  • AVL树的四种旋转
  • 【Python 语法糖小火锅 · 第 4 涮】
  • 资深全栈工程师面试题总结
  • 【牛客刷题】小红的区间删除
  • 第16届蓝桥杯Scratch选拔赛初级及中级(STEMA)2024年11月24日真题
  • Linux之shell脚本篇(四)
  • SQL 172 未完成试卷数大于1的有效用户
  • 9. 堆和栈有什么区别
  • 01数据结构-图的邻接矩阵和遍历
  • 从零开始理解编译原理:设计一个简单的编程语言
  • svg 图片怎么设置 :hover 时变色
  • 交 换
  • sigaction 中 sa_handler = SIG_IGN 的深度解析与应用实践
  • day14 - html5
  • 2025年TOP5服装类跟单软件推荐榜单
  • 复杂正则语句(表格数据)解析
  • CentOS7运行AppImage
  • 历史数据分析——首旅酒店
  • 电子电气架构 --- 48V车载供电架构
  • ubuntu修改密码
  • 基于dynamic的Druid 与 HikariCP 连接池集成配置区别
  • 论文阅读 2025-8-3 [FaceXformer, RadGPT , Uni-CoT]
  • 数论——约数之和、快速乘
  • 新手入门:Git 初次配置与 Gitee 仓库操作全指南 —— 从环境搭建到代码推送一步到位
  • 【unitrix数间混合计算】2.9 小数部分特征(t_non_zero_bin_frac.rs)