欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

算术转换与整形提升

程序员文章站 2024-03-18 11:04:52
...
int main()
{
    char u = 128;
    unsigned char s = 128;
    unsigned short us;
    us = s + u;
    printf("us = 0x%x\n", us);
    us = (unsigned char)u + s;
    printf("us = 0x%x\n", us);
    us = (char)s + u;
    printf("us = 0x%x\n", us);
    return 0;
}

算术转换

  C语言在处理不同类型数值之间的运算时是有一定的规律的。需要先将两个操作数转换为相同的类型才能进行运算。而类型的转换的规律如下图:
  算术转换与整形提升

  • 这里的转换是自动由低向高发生的(当然,强制类型转换是根据用户意愿进行的)。例如:int和unsigned int进行运算,编译器会将低级别的int转换为unsigned int再进行计算。而这个转换编译器并没有对它在内存中的值做出改变,而是使用了不同的读取方式,编译器将原本的int的符号位也当成数值大小进行读取。
  • 而这里没有提到的char和unsigned char,short和unsigned short类型在运算时都会自动为‘升级’为int型再进行运算。也就是整形提升

整形提升

  相应的,不同的低级别的类型向高级别类型整形提升的过程也是不太一样的。   
  这里的转换的规律是:
  unsigned char在转化时,编译器会将他们当成正数进行转化,在高位补0,补全后就是它的补码
  signed char转化时,编译器则会根据他们的正负将他们的高位全部补0或补1,补全后就是它的补码

了解清楚概念后,在来看原题:

    char u = 128;
    unsigned char s = 128;
    unsigned short us;
    us = s + u;
    printf("us = 0x%x\n", us);
  • 128的补码是00000000 00000000 00000000 10000000
  • usigned char型(-128–127)的,将128放到u时截断,u10000000,即-128。同理,unsigned char型(0–255)的s128
  • 当进行s+u算数运行时,先进行整形提升。此时u-128负数,所以前32位补1,即 11111111 11111111 11111111 10000000;s128正数,所以前32补0,即 00000000 00000000 00000000 10000000
  • s和u的值相加得
    00000000 00000000 00000000 10000000   //s的补码  无符号相当于正数,原反补一样,提升为整型时,高位补0,
    11111111 11111111 11111111 10000000   //u提升为整型的补码 u是signed char
+   -----------------------------------
 [1]00000000 00000000 00000000 00000000

又因为usunsigned short型,进行截断,即00000000 00000000,故us=0

    us = (char)s + u;
    printf("us = 0x%x\n", us);

s强转换成char型,s10000000,即-128;与u相加先整形提升,即

    11111111 11111111 11111111 10000000   //u提升为整型的补码 u是signed char
    11111111 11111111 11111111 10000000   //s被强制类型转换后,与u有了相同的待遇
+   -----------------------------------
 [1]11111111 11111111 11111111 00000000

在进行截断赋值给us,即11111111 00000000,为ff00

    us = (unsigned char)u + s;
    printf("us = 0x%x\n", us);

同理,就不阐述了,算出来us为0000000100000000,即100;

程序最后验证结果:

算术转换与整形提升

相关标签: 总结