C语言中数据类型转换“陷阱”

    技术2022-05-20  34

     

    #include <stdio.h>

    void foo(  )

            {

                    unsigned int a=6;

                    int b=-20;

     

                    ( a+b>6 )?puts( ">6" ):puts( "<=6" );               

                    printf( "%u/n",b );

                    printf( "a+b= %u/n",a+b );  

            }

     

    int main()

            {

                    foo(  ) ;

                    return 0;

     

            }

    如果不看foo()中的两个printf的话,我也不会相信结果是输出了“>6”,真是自己掌握得不牢固,原来以为不用管那些太基本的东西(比如c默认的数据类型转换,此题出的恰恰就是这一点);

    先看结果(我用的gcc4.4版本):

    >6

    4294967276

    4294967282

    究其原因就是在使用a+b的时候int-->unsigned int,-20会转换成4294967276,那为什么会是4294967276而不是别的那?

    :-),有点意思了,朋友们应该还记得“溢出“这个概念吧,包括正溢和负溢,比如一个8bit的有符号数表示的数据范围是-128~127,当让这个数去等于大于127的时候会正溢,等于小于-128的时候回产生负溢,这时候的数据就像被放在一个环上一样,只能在-128~127之间,超过了会怎样?就像把int -20转成unsigned int,答案是:

    产生负溢的时候:=环上的最大值-该数的绝对值   (在intel x86 cpu中int是32bit的,比如2^32=4294967296,然后4294967276=4294967296-|-20|,这就是问题的答案)

    产生正溢的时候:=环上的最小值+该数的值

     

    另外自己也找了一些关于c语言的数据类型的麼认转化:

    http://blog.ednchina.com/sealove518/116361/message.aspx

    ● 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128~127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围是0~255(有些机器把char型当做unsighed char型对待, 取值范围总是0~255)。

    ● 如果一个运算符两边的运算数类型不同,先要将其转换为相同的类型,即较低类型转换为较高类型,然后再参加运算,转换规则如下图所示。

    double ←── float 高

    long

    unsigned

    int ←── char,short 低

    ● 图中横向箭头表示必须的转换,如两个float型数参加运算,虽然它们类型相同,但仍要先转成double型再进行运算,结果亦为double型。 纵向箭头表示当运算符两边的运算数为不同类型时的转换,如一个long 型数据与一个int型数据一起运算,需要先将int型数据转换为long型, 然后两者再进行运算,结果为long型。所有这些转换都是由系统自动进行的, 使用时你只需从中了解结果的类型即可。这些转换可以说是自动的,但然,C语言也提供了以显式的形式强制转换类型的机制。

    ● 当较低类型的数据转换为较高类型时,一般只是形式上有所改变, 而不影响数据的实质内容, 而较高类型的数据转换为较低类型时则可能有些数据丢失。

    赋值中的类型转换

    当赋值运算符两边的运算对象类型不同时,将要发生类型转换, 转换的规则是:把赋值运算符右侧表达式的类型转换为左侧变量的类型。具体的转换如下:

    (1) 浮点型与整型 

    ● 将浮点数(单双精度)转换为整数时,将舍弃浮点数的小数部分, 只保留整数部分。

    将整型值赋给浮点型变量,数值不变,只将形式改为浮点形式, 即小数点后带若干个0。注意:赋值时的类型转换实际上是强制的。

    (2) 单、双精度浮点型 

    ● 由于C语言中的浮点值总是用双精度表示的,所以float 型数据只是在尾部加0延长为doub1e型数据参加运算,然后直接赋值。doub1e型数据转换为float型时,通过截尾数来实现,截断前要进行四舍五入操作。 

    (3) char型与int型 

    ● int型数值赋给char型变量时,只保留其最低8位,高位部分舍弃。 

    ● chr型数值赋给int型变量时, 一些编译程序不管其值大小都作正数处理,而另一些编译程序在转换时,若char型数据值大于127,就作为负数处理。对于使用者来讲,如果原来char型数据取正值,转换后仍为正值;如果原来char型值可正可负,则转换后也仍然保持原值, 只是数据的内部表示形式有所不同。 

     

    (4) int型与1ong型 

    ● long型数据赋给int型变量时,将低16位值送给int型变量,而将高16 位截断舍弃。(这里假定int型占两个字节)。 

    将int型数据送给long型变量时,其外部值保持不变,而内部形式有所改变。 

    (5) 无符号整数 

    ● 将一个unsigned型数据赋给一个占据同样长度存储单元的整型变量时(如:unsigned→int、unsigned long→long,unsigned short→short) ,原值照赋,内部的存储方式不变,但外部值却可能改变。

    ● 将一个非unsigned整型数据赋给长度相同的unsigned型变量时, 内部存储形式不变,但外部表示时总是无符号的。 

     

    ● 计算机中数据用补码表示,int型量最高位是符号位,为1时表示负值,为0时表示正值。如果一个无符号数的值小于32768则最高位为0,赋给 int型变量后、得到正值。如果无符号数大于等于32768,则最高位为1, 赋给整型变量后就得到一个负整数值。反之,当一个负整数赋给unsigned 型变量时,得到的无符号值是一个大于32768的值。 

    ● C语言这种赋值时的类型转换形式可能会使人感到不精密和不严格,因为不管表达式的值怎样,系统都自动将其转为赋值运算符左部变量的类型。 

    ● 而转变后数据可能有所不同,在不加注意时就可能带来错误。 这确实是个缺点,也遭到许多人们批评。但不应忘记的是:c面言最初是为了替代汇编语言而设计的,所以类型变换比较随意。当然, 用强制类型转换是一个好习惯,这样,至少从程序上可以看出想干什么。 

     csdn.net//js/topnav.htmlDhttp

     


    最新回复(0)