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

【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语言中,类型转换分为显式类型转换和隐式类型转换两种方式。C++ 也支持这些 C 风格的转换,但推荐使用更安全的 C++ 风格类型转换操作符。

具有C风格的强制类型转换:式类型转换、隐式类型转换一、隐式类型转换 (Implicit Type Conversion) 隐式类型转换,又称自动类型转换,是编译器在不需要程序员显式指定的情况下自动进行的类型转换。

常见场景: 赋值时类型不匹配

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

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

代码语言:javascript复制int i = 42;

double d = i; // 隐式将int转换为double

float f = 3.14f;

double sum = f + d; // 隐式将f提升为double

void func(double x);

func(i); // 隐式将int转换为double转换规则:算术转换 (Arithmetic Conversion):1、小类型向大类型转换;

2、整型向浮点型转换;

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

整数提升 (Integer Promotion):1、char、short 等小整型在运算时自动提升为 int。

二、显式类型转换 (Explicit Type Conversion)使用强制类型转换运算符显式指定转换。

C 风格强制转换语法:代码语言:javascript复制(type_name) expression

// 或

type_name (expression) // C++ 中可用我们举个例子:

代码语言:javascript复制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、指针类型转换非常危险。

代码语言:javascript复制int x = 10;

char *p = (char *)&x; // 危险:可能违反严格别名规则三、C++ 中的改进(对比)C++ 提供了四种更安全的类型转换操作符:

1、static_cast —— 用于良性转换

2、const_cast —— 去除 const 属性

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

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

代码语言:javascript复制double d = 3.14;

int i = static_cast(d); // C++推荐方式实践

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

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

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

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

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

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

1、常见的隐式类型转换场景(1) 算术转换 (Arithmetic Conversion)当表达式中包含不同类型的操作数时发生:

代码语言:javascript复制int i = 5;

double d = 2.5;

double result = i + d; // i被隐式转换为double(2) 赋值转换 (Assignment Conversion)当赋值运算符两侧类型不一致时:

代码语言:javascript复制int i;

double d = 3.14;

i = d; // d被隐式转换为int,小数部分被截断(3) 函数调用转换 (Function Call Conversion)实参与形参类型不匹配时:

代码语言:javascript复制void func(double x);

func(5); // int 5被隐式转换为double 5.0(4) 返回类型转换 (Return Conversion)返回类型与函数声明类型不一致时:

代码语言:javascript复制double func()

{

return 5; // int 5被隐式转换为double 5.0

}2、隐式转换的规则体系(1) 整数提升 (Integer Promotion) char、short等小整型自动提升为int

代码语言:javascript复制char c1 = 'A', c2 = 'B';

int result = c1 + c2; // char提升为int再相加(2) 寻常算术转换 (Usual Arithmetic Conversion)按以下优先级转换(低→高):

bool、char、short → int

int → unsigned int

unsigned int → long

long → unsigned long

unsigned long → long long

long long → unsigned long long

整型 → float

float → double

double → long double

(3) 有符号与无符号转换代码语言:javascript复制unsigned int u = 10;

int i = -5;

if (i < u)

{ // i被转换为unsigned int,结果可能出乎意料

// 这里可能不会执行

}3、隐式转换的风险代码语言:javascript复制int i = 300;

char c = i; // 可能溢出,结果依赖于实现二、显式类型转换 显式类型转换是程序员明确指定的类型转换,也称为强制类型转换。

1、C风格的显式转换语法:

代码语言:javascript复制(type_name) expression

// 或

type_name (expression) // C++风格(1) 基本类型转换代码语言:javascript复制double d = 3.14159;

int i = (int)d; // 截断小数部分,i=3(2) 指针类型转换代码语言:javascript复制int x = 10;

char *p = (char *)&x; // 重新解释内存(3) 函数指针转换代码语言:javascript复制void (*func_ptr)() = (void (*)())some_function;2、C++风格的显式转换 C++提供了四种更安全的转换操作符——

(1) static_cast用于良性转换,编译时检查:

代码语言:javascript复制double d = 3.14;

int i = static_cast(d);(2) const_cast移除const/volatile属性:

代码语言:javascript复制const int ci = 10;

int *pi = const_cast(&ci);(3) dynamic_cast用于多态类型的安全向下转换:

代码语言:javascript复制Base* b = new Derived();

Derived* d = dynamic_cast(b);(4) reinterpret_cast低层重新解释,最危险:

代码语言:javascript复制int i = 10;

float f = reinterpret_cast(i);3、显式转换的风险示例(1) 数据截断代码语言:javascript复制double d = 3.9;

int i = (int)d; // i=3,小数部分丢失(2) 指针误用代码语言:javascript复制int x = 0x12345678;

char *p = (char *)&x;

if (*p == 0x78)

{

// 依赖于字节序

// 在小端机器上成立

}(3) 类型双关 (Type Punning)代码语言:javascript复制float f = 3.14f;

unsigned u = *(unsigned *)&f; // 违反严格别名规则三、实践方面的建议 优先使用隐式转换:当转换安全且意图明显时

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

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

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

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

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

代码语言:javascript复制static_assert(sizeof(int) == 4, "int must be 4 bytes");四、典型面试问题1、以下代码的输出是什么?

代码语言:javascript复制unsigned int u = 10;

int i = -5;

if (i < u)

{

printf("True");

}

else

{

printf("False");

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

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

代码语言:javascript复制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风格的强制类型转换:显式类型转换、隐式类型转换。

🎈 相关推荐

逸龙剑-抉择(史诗制作)
beat365官方网站正规

逸龙剑-抉择(史诗制作)

📅 01-26 👀 7447
石家庄哪里有灯具市场?最全的地方。 , 石家庄灯具批发市场哪里便宜
微博推广全攻略:提升影响力与粉丝数
beat365官方网站正规

微博推广全攻略:提升影响力与粉丝数

📅 12-29 👀 8751