c语言,数据类型转换

在执行算术运算时,计算机比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种浮点型,这还不包括字符型)。 html

当发生下列状况时会进行隐式转换: 程序员

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

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

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

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

隐式类型转换规则:
  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。当把浮点类型数据转换为整数类型时,他们被趋零截尾或舍入。

函数

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

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

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

先来看一段简单的代码:

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章 基本类型。

相关文章
相关标签/搜索