C语言的本质(5)——类型转换的本质与处理
数据类型转换的方式
C 语言中的数据类型转换可分为隐式转换和显式转换两种。
隐式转换
隐式转换也可称作为自动转换,它经常以以下几种形式发生:
1、在计算一个同时出现多种数据类型的表达式时,将所有数据类型都转换为同一种数据类型。
2、在对数据进行输出时,按指定格式将数据输出。
3、利用赋值运算符将数据转换为运算符左边指定的数据类型。
4、在对函数调用时,如果形参与实参的数据类型不一致,实参会自动转换为形参的数据类型。
根据转换发生的形式,可将隐式转换分为类型:一般算术转换、输出转换、赋值转换与函数调用转换。
一般算术转换
这种转换类型会经常出现,它是通过编译器自动实现的,不同类型的数据在一个表达式中会自动转换为最长的类型,例如:
有如下定义char a; int b,e; float c; double d;
计算a*b+c-d/e 时,按计算顺序说明类型转换:
1、 a*b; // char 类型的a 转换为int 类型的值, 再和int 类型的b 相乘。
2、d/e; // int 类型的e 转换为double 类型的值,然后double类型的d 再和e 相除。
3、a*b+c; // int 类型的a*b 转换为float 类型值,再和float 类型的c 相加。
4、a*b+c-d/e; // float 类型的(a*b+c)转换为double 类型的值,再和double类型的d/e 相减。
不考虑过程,最终表达式的值为最长类型(这里是double)的值。
格式输出转换
这种转换类型是将某种类型的数据按照输出格式转换成指定格式。例如:
main(){int a=65;printf("%c\n",a);} //输出“A”
此程序是将ASCII 值为65 的字符输出来,所以输出结果是“A”。
赋值转换
在这种转换中,会出现赋值运算符“=”,就是要将运算符右边的数据类型转换为运算符左边的数据类型,例如:
int main()
{
inta=3.15;
printf("%d\n",a);
} //输出结果是3
之所以会出现这种结果,就是因为运算符右边的3.15 是浮点型常量,它要被转换为运算符左边的整型数据,导致整型变量被赋
值为3。
函数调用转换
此种类型的转换主要会出现在函数调用时形参跟实参数据类型发生不一致的场合,例如:
int mul(int x,int y) //函数中的形参为int
{
int a;a=x*y;
return(a);
}
int main()
{
float a=1.23,b=2.35;
int c;c=mul(a,b); //调用函数时,由于实参是float,所以实参首先会转换为int,再执行函数体部分
printf("%d",c);
} //输出结果是2
显式转换
显式转换可分为两种,即强制性数据类型转换以及利用标准函数转换。
强制性数据类型转换
强制性数据类型转换是将某一种数据类型强制转换为另外一种数据类型。这一种较常见。强制性数据类型转换的一般格式为:
(类型标识符)表达式
例如:
int main()
{
float a=5.6,b=2.3;
printf("%d\n",(int)a%(int)b);
}
由于运算符“%”要求两个数据必须为int 类型,如果不进行强制性数据类型转换,则系统会提示出错信息,所以浮点型数据a 和
b 先各自转换为整型数据5 和6,再进行求余运算,输出结果是1。
标准函数转换
这种转换是利用C 语言中的标准函数将某一种数据类型转换为另外一种数据类型。例如:
int main(void)
{
int a; float b ; char*c="123.45xy", *d;
b=atof(c); //将字符串c 转换为float 型数据
a=atoi(c); //将字符串c 转换为int 型数据
itoa(a,d,10); //将十进制数a 转换为字符串数据并且存放在字符型指针d 所指向的字符串
printf("%.4f,%d,%s\n",b,a,d); //将浮点型数据b、整型数据a 以及字符串数据d 分别按照浮点型、十进制数整型和字符串格式
输出,输出结果是:123.4500,123,123
}
常见问题
在对数据类型进行转换时,是为了程序的需要,可有的时候却会带来意想不到的安全隐患和错误,这就是非安全转换、输入输
出格式错误与运算符数据不匹配。
1、非安全转换
非安全转换是将一种数据类型长的转换成其它数据类型短的数据,使其值的表示范围被缩小所出现的错误。它有如下几种情
况:
较大整数转换为较短的类型
C 语言系统一般不检测这种类型的错误,大部分的编译器在可能出现非安全转换是不会给出警告信息,因此在编程时需避免此
类型转换。
如
int main()
{
long i=123456;
printf("%d\n",i);
} //其输出结果为-6716.
又如
int main(){
unsigned i=65535;
int j ;
j=i;
printf("%d\n",j)
}//输出结果为-1.
有符号负数转换为无符号数
例如:
int main()
{
int i=-1;
printf("%u",i);
} //其结果为65535
当由有符号数转换为无符号数时,原来的符号位将不作为符号,而作为数据的一部分。
双精度类型转换为单精度类型
例如:
int main()
{
double i=10.123456789;
float j=i;
printf("%.9f\n",j);
} //输出为10.123456955
int main()
{
double i=12345678912345.123;
float j=i;
printf("%f\n",j);
} //输出为12345679020032.000000
由于双精度类型转换成单精度类型时,可能出现以下两种情况:其一,降低精度,截断尾数,保留前8 位有效数字,后面的数字
无意义,如例1;其二,若数值超出了单精度所表示的范围,则得到的数据无意义,且系统不提示错误,因此在遇到较大的数据,或对
数据精度要求比较高时,应避免进行此类的转换。
浮点数转换为整型
当浮点数转换成整型数据时,舍弃小数,不进行四舍五入,例如:
int main()
{
double i=15.99999;
int j=i;
printf("%d\n",j);
} //其输出为15
因此,若需要计算结果尽可能高的精度,应避免此种类型的转换。
2、输入输出格式错误
这种错误会出现在格式输入与格式输出函数中。例如:
int main()
{
int i=2;
printf("%f",i);
} //会出现编译错误(数据类型不一致)
3、算术运算“/”、“%”与数据类型不匹配
例如:
int main( )
{
int i=7,j=2;
printf("%d\n",i/j);
} //输出结果为3
程序的本来目的是想得到结果3.5,可是结果却是3,,是因为变量i 和j 都是int 类型的,其结果也是int 类型的,如果
想得到3.5 的话,就要将i 和j 都要强制转换为float 类型;
int main( )
{
float i=12.45,j=6.3;
printf("%d\n",i%j);
} //提示错误: 非法地使用浮点数在main函数中
之所以会出现系统提示错误,是因为运算符“%”左右两侧的数
据类型都必须是int,但程序中两个变量却都不是int 类型的,因此,想让系统不出错误,就必须将两个变量都强制转换为float 类型。
从上述两个例子来看,对于算术运算符“/”和“%”,一定要注意数据类型的匹配。
在C 语言中,多种数据类型之间的转换有它出现的必然性,也就是在某些情况下,数据转换是必须的,但应尽量避免出现将数
据长的类型转换为数据短的类型、输入输出格式上的错误以及运算符数据类型不匹配等问题。
C语言的本质(5)——类型转换的本质与处理的更多相关文章
- C语言提高 (1) 第一天 数据类型本质与内存四区
(物联网的分层的概念 b/s c/s 结构 习惯: 在C语言 0 函数执行成功 <0是错误 >1做一些返回值处理 3 课前准备 工作经验,记录 4 数据类型的本质 数据类型的本质是固定大小 ...
- C语言中动态内存分配的本质是什么?
摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...
- 李洪强漫谈iOS开发[C语言-002]-开发概述程序的本质与简单执行过程
李洪强iOS开发之应用程序的本质与简单执行过程 什么叫程序? 就是一段执行指令 程序的两个状态: 保存状态(保存到硬盘上) 运行状态(由CPU执行) 代码可以执行吗? CPU(中央处理器-> ...
- C语言的本质(31)——C语言与汇编之函数调用的本质
我们一段代码来研究函数调用的过程.首先我们写一段简单的小程序: int sum(int c, int d) { inte = c + d; returne; } int func(int a, int ...
- C语言中强制数据类型转换(转)
原文地址不详 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围是0-255(有些 ...
- C语言-逃逸字符、类型转换和布尔类型
C语言-逃逸字符 逃逸字符是用来表达无法印出来的控制字符或者特殊字符,它由一个反斜杠""开头,后面跟上另一个字符,这两个字符合起来,组成一个字符. \b是backspace,在su ...
- Java | this的本质 和 static的本质
this 在说this之前先说一下,对象创建的过程: 1.分配对象空间,并将对象成员变量初始化. 2.执行属性值的显式初始化. 3.执行构造方法. 4.返回相关的地址给相关的对象. this的本质 ...
- C语言隐式强制类型转换
今天又被精度问题困扰,把最基本的东西忘了. int n = 5; int cnt = 5.5; double sum = (n-cnt); 运算完后sum是 -0.5.不知道什么时候n转换成doub ...
- C语言系列之强制类型转换(一)
例子: #include <stdio.h> { char cChar; //字符型变量 short int iShort; //短整型变量 int ilnt; / ...
随机推荐
- js分页代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xh ...
- encoding(hdoj1020)
Problem Description Given a string containing only 'A' - 'Z', we could encode it using the following ...
- SQL Server 的内存分类
第一类. 根据申请方式分: commit 型 它是指先reserve申请一大块,再通过commit提交后得到的空间.这种方式申请到的空间可以启用 awe ! stolen型 与commit 相对应!它 ...
- Oracle EBS-SQL (BOM-19):主BOM与替代BOM互换.sql
替代BOM与主BOM互相转换 BOM: 1-01-27-211 子件:1-01-27-416 ID:2202 BOM替代项:替代0001 子件: 1-01-26-204 ID:2 ...
- 类加载器子系统——JVM之四
一.类加载器基本概念 顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java ...
- create custom launcher icon 细节介绍
create custom launcher icon 是创建你的Android app的图标 点击下一步的时候,出现的界面就是创建你的Android的图标 Foreground: ” Foregro ...
- C++ new和delete实现原理——new和delete最终调用malloc和free
new和delete最终调用malloc和free,关于malloc和free实现原理参见这篇文章: http://blog.csdn.net/passion_wu128/article/detail ...
- QWidget 键盘事件 焦点(源代码级别研究)
在Qt中,键盘事件和QWidget的focus密不可分:一般来说,一个拥有焦点(focus)的QWidget或者grabKeyboard()的QWidget才可以接受键盘事件. 键盘事件派发给谁? 如 ...
- Memory Leak(内存泄漏)问题总结(转)
最近听了一些关于Memory Leak(内存泄漏)的seminar,感觉有些收获,所以留个记录,并share给朋友. 1 什么是Memory Leak. Memory Leak是指由于错误或不完备的代 ...
- 三校联考 Day3
三校联考 Day3 大水题 题目描述:给出一个圆及圆上的若干个点,问两个点间的最远距离. solution 按极角排序,按顺序枚举,显然距离最远的点是单调的,线性时间可解出答案. 大包子的束缚 题目描 ...