C语言不踩坑: 自动类型转换规则

先看一个例程:

# include <stdio.h>
int main(void)
{
    
    
    int a = -10;
    unsigned b = 5;
    if ((a+b) > 0)
    {
    
    
        printf("(a+b) > 0\n");
        printf("(a+b) = %d\n",a+b);
    }
    else
    {
    
    
    	printf("(a+b) <= 0\n");
	}
    return 0;
}

运行的结果是:

(a+b) > 0
(a+b) = -5

看完这个结果会产生疑问:-10+5不是小于0的吗?怎么会在判断的时候大于0,而且打印值的时候也显示就是-5。

这是因为有个自动转换的规则:有符号整型和无符号整型混合运算时,有符号型自动转换成无符号型,运算的结果是无符号的。
在判断(a+b)>0时,由于b是无符号整型,而a是有符号整型,因此a会变成无符号整型则变成一个很大的数再与b相加,结果还是很大的正数,所以判断大于0。

为什么里面打印a+b的值时却是正常的-5呢?首先我们要知道加法的计算机底层逻辑其实是按位相加,得到的结果数同样的内存数据,翻译成有符号数和无符号数都可以,a+b的结果-5从内存里看,与一个很大的无符号数的内存数据是一样的,前面判断(a+b)>0时,是按-5的内存数据无符号状态去和0比,后面打印结果时,用的是%d打印的是按有符号数据输出,即使a+b的结果是一个很大的无符号数,但按有符号看待的话结果就出来-5。
所以那是被%d输出符号影响了,换个C++程序再看:

#include <iostream>
 
int main()
{
    
    
    int a = -10;
    unsigned int b=5;
    std::cout << a+b;
    return 0;
}

结果是:
在这里插入图片描述

这个题目告诉我们,平时写代码时,要注意运算式中是否有不同类型数混合,因尽量避免不确定性,最好用强制类型转换注明,否则可能会产生意外的结果。

如果参与运算的数据类型不同,会自动转化为同一类型再运算。这就是自动转换。
自动转换的规则如下:

  1. 当参与运算的数据的类型不同时,编译系统会自动先将它们转换成同一类型,然后再进行运算。

但问题是转换的时候是谁转换成谁呢?转换的基本规则是“按数据长度增加的方向进行转换”,以保证精度不降低。比如 int 型数据和 long 型数据进行相加或相减运算时,系统会先将 int 型数据转换成 long 型,然后再进行运算。这样的话运算结果的精度就不会降低。

long 是“大水桶”,int 是“小水桶”。int 能存放的,long 肯定能存放;而 long 能存放的,int 不一定能存放。

  1. 所有的浮点运算都是以双精度进行的。

在运算时,程序中所有的 float 型数据全部都会先转换成 double 型。即使只有一个 float 型数据,也会先转换成 double 型,然后再进行运算。为什么要这样呢?因为 CPU 在运算的时候有“字节对齐”的要求,这样运算的速度是最快的。

  1. char 型和 short 型数据参与运算时,必须先转换成 int 型。这也是涉及 CPU 的运行原理的。

  2. 有符号整型和无符号整型混合运算时,有符号型要转换成无符号型,运算的结果是无符号的。

  3. 整型和浮点型混合运算时,整型先转换成浮点型,运算的结果是浮点型。
    (2)(3)(4)(5)四条规则总结起来,当类型混合运算时,按如下级别转换:

doublefloatlongunsignedintcharshort

在这里插入图片描述

  1. 在赋值运算中,当赋值号两边的数据类型不同时,右边的类型会转换为左边的类型,然后再赋给左边。如果右边数据类型的长度比左边长,那么将会丢失数据,这样就会降低精度,所以编译的时候会产生警告。如果右边精度低于左边,则输出正常计算结果。
    比如:
    int a;
    float b=9.9;
    float c=2.2;
    a=b+c;//a结果是12
    这个过程是9.9和2.2先转成double进行运算得到12.1。然后再转换为左边的int型,即只取整数。

猜你喜欢

转载自blog.csdn.net/weixin_44788542/article/details/129334945