在执行算术运算时,计算机比C语言的限制更多。为了让计算机执行算术运算,通常要求操作数有相同的大小(即位的数量相同),并且要求存储的方式也相同。计算机可能可以直接将两个16位整数相加,但是不能直接将16位整数和32位整数相加,也不能直接将32位整数和32位浮点数相加。另一方面,C语言允许在表达式中混合使用基本数据类型。在单独一个表达式中可以组合整数、浮点数,甚至是字符。当然,在这种情况下C语言编译器可能需要生成一些指令将某些操作数转换成不同类型,使得硬件可以对表达式进行计算。例如,如果对16位int型数和32位long int型数进行加法操作,那么编译器将安排把16位int型值转换成32位值。如果是int型数据和float型数据进行加法操作,那么编译器将安排把int型值转换成为float格式。这个转换过程稍微复杂一些,因为int型值和float型值的存储方式不同。因为编译器可以自动处理这些转换而无需程序员介入,所以这类转换称为隐式转换(implicit conversion)。C语言还允许程序员通过使用强制运算符执行显式转换(explicit conversion)。首先讨论隐式转换,,执行隐式转换的规则有些复杂,主要是因为C语言有大量不同的基本数据类型(6种整型和3种浮点型,这还不包括字符型)。

当发生下列情况时会进行隐式转换:

.当算术表达式或逻辑表达式中操作数的类型不相同时。(C语言执行所谓的常用算术转换。)

.当赋值运算符右侧表达式的类型和左侧变量的类型不匹配时。

.当函数调用中使用的参数类型与其对应的参数的类型不匹配时。

.当return语句中表达式的类型和函数返回值的类型不匹配时。

隐式类型转换规则:
  C语言自动转换不同类型的行为称之为隐式类型转换 ,转换的基本原则是:低精度类型向高精度类型转换,具体是:
  int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long -> float -> double -> long double

  注意,上面的顺序并不一定适用于你的机器,比如当int和long具有相同字长时,unsigned int的精度就会比long的精度高(事实上大多数针对32机的编译器都是如此)。另外需要注意的一点是并没有将char和short型写入上式,原因是他们可以被提升到int也可能被提升到unsigned int。
  提升数据的精度通常是一个平滑无损害的过程,但是降低数据的精度可能导致真正的问题。原因很简单:一个较低精度的类型可能不够大,不能存放一个具有更高精度的完整的数据。一个1字节的char变量可以存放整数101但不能存放整数12345。当把浮点类型数据转换为整数类型时,他们被趋零截尾或舍入。

当把有符号操作数和无符号操作数整合时,会通过把符号位看成数的位的方法把有符号操作数"转换"成无符号的值.这条规则可能会导致某些隐蔽的编程错误。

假设int型的变量i的值为-10,而且unsigned int型的变量u的值为10。如果用<运算符比较变量i和变u,那么期望的结果应该是1(真)。但是,在比较前,变量i转换成为unsigned int类型。因为负数不能被表示成无符号整数,所以转换后的数值将不再为-10,而是一个大的正数(将变量i中的位看作是无符号数).因此i<u比较的结果将为0。

由于此类陷阱的存在,所以最好尽最避免使用无符号整数,特别是不要把它和有符号整数混合使用。

先来看一段简单的代码:

  1 #include <stdio.h>
  2
  3 int array[] = {1, 2, 3, 4, 5, 6, 7};
  4 #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
  5
  6 int main()
  7 {
  8     int i = -1;
  9     int x;
 10
 11     if(i <= TOTAL_ELEMENTS - 2) {
 12         x = array[i + 1];
 13         printf("x = %d.\n", x);
 14     }
 15
 16     printf("now i = %d.\n", TOTAL_ELEMENTS);
 17
 18     return 0;
 19 }

执行结果:

randy@ubuntu:~/C_Language$ ./a.out

now i = 7.

是不是很奇怪?为什么没有打出line13的x = ?。

是这样的。这个小例子有三点值得注意:

1.sizeof()是运算符,返回类型是无符号的,即非负数。

2.if语句在singned int和unsigned int之间进行判断语句,根据C语言的整型提升规则,int -> unsigned int

3.i = -1被升级为无符号型,值究竟是多少?这要用到整型转换规则:K&R上这样解释,将任何整数转换为某种指定的无符号数类型数的方法是:以该无符号数类型能够表示的最大值加1为摸,找出与此整数同余的最小的非负值。听着很拗口,其实说白了,只要知道原整数的二进制表达方法,再用要即将转换的类型去解析,就得到升级后的值了。 比如-1,负数在计算机里用补码表示为0xffffffff,那升级成无符号型之后,值就是0xffffffff,显然比TOTAL_ELEMENTS(7)大。

---------------------------------------------------------------------------------------------

强制类型转换:

通常我们应该避免自动类型转换,当我们需要手动指定一个准确的数据类型时,我们可以用强制类型转换机制来达到我们的目的,使用方法很简单,在需要强制转换类型的变量或常量前面加上(type),例如(double)i; 即把变量 i 强制转换成double型。

思考下面这个例子:

long int i;

int j = 10000;

i = j*j; /*wrong*/

乍看之下,这条语句没有问题。表达式j*j的值是1000000,并且变量i是long int型的,所

以i应该能很容易地存储这种大小的值,不是吗?问题是,当两个int型值相乘时,结果也应该

是int类型的,但是j*j的结果太大,以致于在某些机器上无法表示成int类型.在这样的机器

上,会给变量i赋一个无意义的值。幸运的是,可以使用强制类型转换避免这种问题的发生:

i=(long int)j*j

因为强制运算符的优先级高于*,所以第一个变量j会被转换成long int类型,同时也迫使第

二个j进行转换。

注意语句

i==(long int)(j*j)/**WRONG***/

是不对的,因为溢出在强制类型转换之前就己经发生了。

Q&A:

问:如果"溢出"会发生什么?比如,两个数相加的结果过大而无法存储.

答:这取决于数是有符号型的还是无符号型的。当溢出发生在有符号数的操作上时,依据C语言的标准,

结果是"未定义的"。我们无法准确说出结果是什么,因为这依赖于机器的行为。程序甚至可能会

异常中断(对除以零的典型反应)。

但是,当溢出发生在无符号数的操作上时,结果是定义了的:可以获得正确答案对2n进行取模运算

的结果,这里的n是用于存储结果使用的位数。例如,如果用1加上无符号的16位数65535,那么结

果肯定是65536 (已经溢出,但计算机能正确表示其值).

int t1()
{
short int i = 65535;
short int j = 1;
unsigned short int uj = 1;
unsigned short int ui = 65535; printf("i + j = %d\n" , i + j);
printf("i + uj = %d\n" , i + uj);
printf("ui + uj = %d\n" , ui + uj);
printf("ui + 1 = %d\n" , ui + 1); } /*
root@oucaijun:/work/dcc# gcc 1.c ;./a.out
i + j = 0
i + uj = 0
ui + uj = 65536
ui + 1 = 65536 */

  

---------------------------------------------------------------------------------------------

笔试题-c语言类型转换(2012.3.23面试)

C语言拾遗(一):整型提升

《C语言程序设计:现代方法》第7章 基本类型。

c语言,数据类型转换的更多相关文章

  1. C语言数据类型转换

    变量的数据类型是可以转换的.转换的方法有两种,一种是自动转换,一种是强制转换. 自动转换 自动转换发生在不同数据类型的量混合运算时,由编译系统自动完成.自动转换遵循以下规则: 若参与运算量的类型不同, ...

  2. R语言数据类型转换

    test for data type is.numeric(), is.character(), is.vector(), is.matrix(), is.data.frame() convert i ...

  3. 谷歌protobuf(protocol-buffers)各种开发语言数据类型转换说明

    官方文档:https://developers.google.cn/protocol-buffers/docs/proto proto2 proto3

  4. C语言中强制数据类型转换(转)

    原文地址不详 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围是0-255(有些 ...

  5. C语言关于数据类型转换

    自动类型转换 自动类型转换就是编译器默默地.隐式地.偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生. 1) 将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,例如: ; ...

  6. C语言:数据类型转换 自动转换 强制转换

    数据类型转换就是将数据(变量.数值.表达式的结果等)从一种类型转换为另一种类型. 自动类型转换 自动类型转换就是编译器默默地.隐式地.偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生.1 ...

  7. 使用变量 数据类型转换 逻辑控制语句(begin ...end; case...end; if...else; while)

    一:变量 变量分为局部变量和全局变量  (全局变量是系统自定的,是不可手动给值的,若想自己定义全局变量可考虑创建全局临时表!) 局部变量的定义:  declare @变量名  数据类型 (局部变量只能 ...

  8. c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast  [版权声明]转载请注明出处 http://www.cnblogs.c ...

  9. JavaScript数据类型转换

    原文转自:http://javascript.ruanyifeng.com/grammar/conversion.html#rd JavaScript是一种动态类型语言,变量是没有类型的,可以随时赋予 ...

  10. js笔记——js数据类型转换

    以下内容摘录自阮一峰的<语法概述 -- JavaScript 标准参考教程(alpha)>章节『数据类型转换』,以做备忘.更多内容请查看原文. JavaScript是一种动态类型语言,变量 ...

随机推荐

  1. java的for循环问题的解决,以及安卓中ListView插入数据的问题

    package test.testdemo; import org.springframework.jdbc.core.JdbcTemplate; import com.util.Pub; publi ...

  2. C#线程应用实例(part1) 之 BeginInvoke和EndInvoke

    最近这个公司是做 winfrom 开发的 , 这段时间就好好的学学WCF , 公司框架什么的自己去琢磨! 这里主要写一些 winfrom 中 用到的一些陌生 技术 1.BeginInvoke  以前B ...

  3. Nginx 之五: Nginx服务器的负载均衡、缓存与动静分离功能

    一.负载均衡: 通过反向代理客户端的请求到一个服务器群组,通过某种算法,将客户端的请求按照自定义的有规律的一种调度调度给后端服务器. Nginx的负载均衡使用upstream定义服务器组,后面跟着组名 ...

  4. WebRTC–getUserMedia & Canvas

    下面是一个使用getUserMedia接口和Canvas的drawImage方法实现的截图功能(截取视频中的一帧). 基本思路是这样子的: getUserMedia获取一个MediaStream, s ...

  5. 转: seajs手册与文档之 -- require规则

    require 规则 正确拼写 不要修改 使用直接量 动态依赖的小提示 书写规则 使用 SeaJS 书写模块代码时,需要遵循一些简单规则: 1. 正确拼写 在模块代码中,第一个参数 必须 命名为 re ...

  6. sortable.js 华丽丽的排序

    首先导入这几个资源 <link href="/css/jquery-ui-1.10.3.custom.css" rel="stylesheet" type ...

  7. 在 Windows Azure 网站 (WAWS) 上对 Orchard CMS 使用 Azure 缓存

    编辑人员注释: 本文章由 Windows Azure 网站团队的项目经理 Sunitha Muthukrishna 撰写. 如果您当前的 OrchardCMS 网站在 Windows Azure 网站 ...

  8. 宣布 Windows Azure 通过 PCI DSS 合规性验证并且 ISO 认证范围扩大,同时正式发布 Windows Azure Hyper-V 恢复管理器和其他更新功能

    今天,我们高兴地宣布两个重大里程碑事件,客户将能借此提高基于 Windows Azure 构建安全且合规的应用程序的能力.此外,我们还宣布正式发布 Windows Azure Hyper-V 恢复管理 ...

  9. BZOJ 1096: [ZJOI2007]仓库建设( dp + 斜率优化 )

    dp(v) = min(dp(p)+cost(p,v))+C(v) 设sum(v) = ∑pi(1≤i≤v), cnt(v) = ∑pi*xi(1≤i≤v), 则cost(p,v) = x(v)*(s ...

  10. Android:mimeType

    接收从其他应用传过来的数据,要用到清单文件 <activity android:name="com.terry.myActivity2" android:label=&quo ...