一篇文章带你看清C语言中的类型转换规则

简介: 笔记

我们平时在学习编程以及平时在进行编程练习的时候,经常会碰见那些类型转换的方面,有的时候我么需要进行强制转换,但有的时候系统却可以自动为我们转换,这到底是为什么呢?下面我们就来了解一下C语言中的类型转换规则吧。


我们所学习的数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题。在C/C++类型转换中,主要分为两种即:隐式类型转换(自动转换)、显式类型转换(强制类型转换)。


自动转换(隐式转换):遵循一定的规则,由编译系统自动完成。

强制类型转换(显示转换):把表达式的运算结果强制转换成所需的数据类型。

这时我们就要了解一个数据转换的基本原则:占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低。

1.png



隐式转换


所谓隐式类型转换,是指不需要用户干预,编译器默认进行的类型转换行为(很多时候用户可能都不知道到底进行了哪些转换)。


隐式类型转换一般分为两种:内置数据类型、自定义数据类型。


内置数据类型

内置数据类型转换的原则也就遵循了我们上面所提到的原则,就是一定要从低精度到高精度去转换才行。


#include <stdio.h>
int main()
{
  int num = 5;
  printf("s1=%d\n", num / 2);
  printf("s2=%lf\n", num / 2.0);
  return 0;
}

2.png


通过我们的运算结果图,也不难发现我们的数据从整形转换为了浮点型,这就发生了一次隐式转换。


所以我们在进行运算时,对于除法运算,如果除数和被除数都是整数,那么运算结果也是整数,小数部分将被直接丢弃;如果除数和被除数其中有一个是小数,那么运算结果也是小数。


如果我们不去满足原则的进行隐式转换,那么编译器将会提示编译告警。


自定义数据类型

内置数据类型的转换风险是很小的,所以隐式类型转换的风险一般存在于自定义类型转换间。尤其需要注意自定义类的构造函数。


class MyString
{
  public:
       MyString(int n) {}; // 预先分配n个字节给字符串
       MyString(const char* p) {}; // 用C风格的字符串p作为初始化值 
  };
 void main()
 {
      MyString s1 = "China";  //成功 隐式转换,等价于MyString s1 = MyString(”China”) 
      MyString s2(10);  //成功 分配10个字节的空字符串
      MyString s3 = MyString(10); //成功 分配10个字节的空字符串
      MyString s4 = 10; //成功,编译通过。也是分配10个字节的空字符串
      MyString s5 = 'A'; // 编译通过。分配int('A')个字节的空字符串
  }

在 s4 和s5 中,分别把一个int型和char型,隐式转换成了分配若干字节的空字符串,这样会容易令人误解。


显示转换


自动类型转换是编译器根据代码的上下文环境自行判断的结果,有时候并不是那么“智能”,不能满足所有的需求。如果需要,程序员也可以自己在代码中明确地提出要进行类型转换,这称为强制类型转换也就是显示转换。


显示转换(强制类型转换)指的是使用强制类型转换运算符,将一个变量或表达式转化成所需的类型,其基本语法格式如下所示:


(类型说明符) (表达式)

#include 
int main()
{
  float x = 0 ;
  int i = 0 ;
  x = 3.f ;
  i = x ;   //x为实型, i为整型,直接赋值会有警告
  i = (int)x ;  //使用强制类型转换
  printf("x=%f, i=%d\n", x, i) ;
  return 0 ;
}

3.png

上面那段代码,后面的i就是使用的强制转换将其从高精度的float类型转化为低精度的int类型,这是在隐式转换中无法做到的一点。


类型转换的临时性

不论是隐式类型转换还是显示类型转换,都只是为了本次运算而进行的临时性转换,转换的结果也会保存到临时的内存空间,所以不会改变数据本来的类型或者值。


#include 
int main(){
  double a = 205.8;  
  int b = 7;  
  double c;  
  int a_int = (int)a;
  c = a / b;
  printf("a=%lf, a_int=%d, c=%lf\n", a, a_int, c);
  return 0;
}

4.png


通过结果我们也不难看出,类型转换是临时的,并不会去改变改变了自身的类型。


两种转换类型的优缺点

在C语言中,有些类型既可以自动转换,也可以强制转换,例如 int 到 double,float 到 int 等;而有些类型只能强制转换,不能自动转换


可以自动转换的类型一定能够强制转换,但是,需要强制转换的类型不一定能够自动转换。现在我们学到的数据类型,既可以自动转换,又可以强制转换,以后我们还会学到一些只能强制转换而不能自动转换的类型。

可以自动进行的类型转换风险较低,不会对程序带来严重的后果,但是只能强制进行的类型转换一般风险较高,或者行为匪夷所思,会导致你得到的结果很奇怪或者导致程序的崩溃。


所以在使用强制类型转换时,程序员自己要意识到潜在的风险。


相关文章
|
2月前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
75 7
|
2月前
|
存储 大数据 编译器
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
|
2月前
|
存储 机器学习/深度学习 编译器
一篇文章,把你的C语言拉满绩点
一篇文章,把你的C语言拉满绩点
16 0
|
3月前
|
存储 C语言
【C语言基础】一篇文章搞懂指针的基本使用
本文介绍了指针的概念及其在编程中的应用。指针本质上是内存地址,通过指针变量存储并间接访问内存中的值。定义指针变量的基本格式为 `基类型 *指针变量名`。取地址操作符`&`用于获取变量地址,取值操作符`*`用于获取地址对应的数据。指针的应用场景包括传递变量地址以实现在函数间修改值,以及通过对指针进行偏移来访问数组元素等。此外,还介绍了如何使用`malloc`动态申请堆内存,并需手动释放。
|
4月前
|
存储 程序员 C语言
揭秘C语言:这些核心知识你掌握了吗?一篇文章带你突破编程基础,开启高效编码之旅!
【8月更文挑战第22天】C语言作为编程基石,以简洁高效著称,历经数十年仍备受欢迎。本文通过梳理C语言的核心概念,帮助读者深入理解并提升技能。适合各水平读者。基础语法从`main`函数开始,如示例中的“Hello, World!”程序所示。C语言强调头文件包含与语句结尾的分号。变量和数据类型丰富多样,如`int`、`float`、`char`等,合理选择可优化内存使用和性能。指针用于间接访问内存,是C语言的关键特性。控制结构如循环和分支使程序逻辑更灵活。函数支持代码复用与模块化。深入学习还需掌握预处理指令、文件操作等高级特性。通过系统学习与实践,你将能更熟练地使用C语言,构建高效稳定的应用。
71 4
|
4月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
|
4月前
|
C语言
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
|
4月前
|
存储 编译器 C语言
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
|
6月前
|
编译器 C语言
【C语言】:中移位操作符,位操作符详运算规则详解
【C语言】:中移位操作符,位操作符详运算规则详解
52 1
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的C语言在线评测系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的C语言在线评测系统附带文章源码部署视频讲解等
54 0