zoukankan      html  css  js  c++  java
  • C++中关于类型转换的问题讨论

    这里以signed/unsigned char, signed/unsigned short, signed/unsigned int类型为例,

    讨论一下基本类型转换的基本原理,这样我们在编程中碰到由类型错误转换而引发的越界问题时,也可以比较容易诊断,不至于把BUG怀疑到机器或编译器身上:)。

    本文属于个人原创,任何个人都可以转载,但请务必提供转载地址。

    一,3种基本类型表示范围如下 (圆形示例图),其中阴影部分的弧边界包含的是没有越界的数值范围:

    2,类型转换原则小结:

    我们把类型转换分成两类:

    1)同类型符号之间的转换:

      *同长度类型,不做转换,如int->int,

      *向更长度类型转换,如char->short->int

      原则:向高字节对齐

           因为有足够位数容纳数值,所以数值会保持不变;

         若为负数时高位会被1,若为正数时高位会补0.

          *向短长度类型转换:如int ->short->char

           原则:高字节截断,低字节保留。

    2)不同类型符号之间的转换:

      *同长度类型转换:如int<->unsigned int

      原则:重新解释至目标类型,

          这里是重新解释,换名话说,在等长字节时,有符号类型和无符号类型在内存中的十六进制表示仍然是一样的。

         当数值范围溢出时,重新解释会造成前后两者数值的会发生巨大跳变,详见示例。

      *向更长类型转换:如char->unsigned int

      原则:先字节对齐,再类型统一。

         如:char->unsigned int  ===>char -> int ->unsigned int

                      unsigned char -> int ===>unsigned char ->unsigned int ->int

      这个原则会造成将负数执行”跨类型跨字节“转换时,前后两数值之间很大差距,

      如果想让差距变得”相对“合理些(等价于重新解释后的数值),你需要手动做强制转换:先类型统一,再做字节对齐。

      *向更短字节对齐:如int->unsigned char

      原则:高字节截断,低字节保留

    提示:

      1)如果想要转换无错,还是规规矩矩的保证数值:不要溢出,不要截断,不要跨类型跨字节转换。

      2)在”有符号类型“向”无符号类型“转换时,数值不要为负数,否则打印出的数值并非你想要的结果。

      尤其是“有符号短字节类型“向”无符号长字节类型转换“时,负数会按照高字节补1的原则,你将会得到一个无敌错错值。

    3,类型转换源代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    
    typedef char s8;
    typedef unsigned u8;
    typedef short s16;
    typedef unsigned short u16;
    typedef int s32;
    typedef unsigned int u32;
    
    #define NONE "33[0m"
    #define BLUE "33[0;32m"
    #define RED "33[0;31m"
    
    void func_s8(s8 num)
    {
        s8 s8Num     = num;
        u8 u8Num     = num;
        s16 s16Num     = num;
        u16 u16Num     = num;
        s32 s32Num     = num;
        u32 u32Num     = num;
        //signed->signed
        printf(BLUE " s8[%hhd#0x%02hhx]:" NONE "
    s16(%hd#0x%04hx) 
    s32(%d#0x%08x)
    ", 
            s8Num, s8Num, s16Num, s16Num, s32Num, s32Num);
    
        //signed->unsigned 
        printf(" u8(%hhu#0x%02hhx) 
    u16(%hu#0x%04hx) 
    u32(%u#0x%08x)
    ",
            u8Num, u8Num, u16Num, u16Num, u32Num, u32Num);
    }
    
    void func_u8(u8 num)
    {
        s8 s8Num     = num;
        u8 u8Num     = num;
        s16 s16Num     = num;
        u16 u16Num     = num;
        s32 s32Num     = num;
        u32 u32Num     = num;
        //unsigned->unsigned
        printf(BLUE " u8[%hhu#0x%02hhx)]" NONE "
    u16(%hu#0x%04hx) 
    u32(%u#0x%08x)
    ",
            u8Num, u8Num, u16Num, u16Num, u32Num, u32Num);
    
        //unsigned->signed 
        printf(" s8(%hhd#0x%02hhx): 
    s16(%hd#0x%04hx) 
    s32(%d#0x%08x)
    ", 
            s8Num, s8Num, s16Num, s16Num, s32Num, s32Num);
    }
    
    void func_s16(s16 num)
    {
        s8 s8Num     = num;
        u8 u8Num     = num;
        s16 s16Num     = num;
        u16 u16Num     = num;
        s32 s32Num     = num;
        u32 u32Num     = num;
        //signed->signed
        printf(BLUE "s16[%hd#0x%04hx]: " NONE "
    s32(%d#0x%08x) 
     s8(%hhd#0x%02hhx)
    ", 
            s16Num, s16Num, s32Num, s32Num, s8Num, s8Num);
    
        //signed->unsigned 
        printf("u16(%hu#0x%04hx) 
    u32(%u#0x%08x) 
     u8(%hhu#0x%02hhx)
    ",
            u16Num, u16Num, u32Num, u32Num, u8Num, u8Num);
    }
    
    void func_u16(u16 num)
    {
        s8 s8Num     = num;
        u8 u8Num     = num;
        s16 s16Num     = num;
        u16 u16Num     = num;
        s32 s32Num     = num;
        u32 u32Num     = num;
        //unsigned->unsigned
        printf(BLUE "u16[%hu#0x%04hx]:" NONE "
    u32(%u#0x%08x) 
     u8(%hhu#0x%02hhx)
    ",
            u16Num, u16Num, u32Num, u32Num, u8Num, u8Num);
    
        //unsigned->signed 
        printf("s16(%hd#0x%04hx) 
    s32(%d#0x%08x) 
     s8(%hhd#0x%02hhx)
    ", 
            s16Num, s16Num, s32Num, s32Num, s8Num, s8Num);
    }
    
    void func_s32(s32 num)
    {
        s8 s8Num     = num;
        u8 u8Num     = num;
        s16 s16Num     = num;
        u16 u16Num     = num;
        s32 s32Num     = num;
        u32 u32Num     = num;
        //signed->signed
        printf(BLUE "s32[%d#0x%08x]:" NONE "
    s16(%hd#0x%04hx) 
     s8(%hhd#0x%02hhx)
    ", 
            s32Num, s32Num, s16Num, s16Num, s8Num, s8Num);
    
        //signed->unsigned 
        printf("u32(%u#0x%08x) 
    u16(%hu#0x%04hx) 
     u8(%hhu#0x%02hhx)
    ",
            u32Num, u32Num, u16Num, u16Num, u8Num, u8Num);
    }
    
    void func_u32(u32 num)
    {
        s8 s8Num     = num;
        u8 u8Num     = num;
        s16 s16Num     = num;
        u16 u16Num     = num;
        s32 s32Num     = num;
        u32 u32Num     = num;
        //unsigned->unsigned
        printf(BLUE "u32[%u#0x%08x]" NONE "
    u16(%hu#0x%04hx) 
     u8(%hhu#0x%02hhx)
    ",
            u32Num, u32Num, u16Num, u16Num, u8Num, u8Num);
    
        //unsigned->signed 
        printf("s32(%d#0x%08x): 
    s16(%hd#0x%04hx) 
     s8(%hhd#0x%02hhx)
    ", 
            s32Num, s32Num, s16Num, s16Num, s8Num, s8Num);
    }
    
    int main()
    {
        printf(RED "######s8Num testing######
    " NONE);
        s8 s8Num = 0x7F;
        func_s8(s8Num);
        s8Num = 0x80;
        func_s8(s8Num);
        s8Num = 0xFF;
        func_s8(s8Num);
        
        printf(RED "######u8Num testing######
    "NONE);
        u8 u8Num = 0x7F;
        func_u8(u8Num);
        u8Num = 0x80;
        func_u8(u8Num);
        u8Num = 0xFF;
        func_u8(u8Num);
    
        printf(RED "######s32Num testing######
    "NONE);
        s32 s32Num = 0x7FFFFFFF;
        func_s32(s32Num);
        s32Num = 0x80000000;
        func_s32(s32Num);
        s32Num = 0xFFFFFFFF;
        func_s32(s32Num);
        
        printf(RED "######u32Num testing######
    "NONE);
        u32 u32Num = 0x7FFFFFFF;
        func_u32(u32Num);
        u32Num = 0x80000000;
        func_u32(u32Num);
        u32Num = 0xFFFFFFFF;
        func_u32(u32Num);
        
        printf(RED "######s16Num testing######
    "NONE);
        s16 s16Num = 0x7FFF;
        func_s16(s16Num);
        s16Num = 0x8000;
        func_s16(s16Num);
        s16Num = 0xFFFF;
        func_s16(s16Num);
        
        printf(RED "######u16Num testing######
    "NONE);
        u16 u16Num = 0x7FFF;
        func_u16(u16Num);
        u16Num = 0x8000;
        func_u16(u16Num);
        u16Num = 0xFFFF;
        func_u16(u16Num);
        
        return 0;
    }

    4,类型转换运行结果

    ######s8Num testing######
     s8[127#0x7f]:
    s16(127#0x007f) 
    s32(127#0x0000007f)
     u8(127#0x7f) 
    u16(127#0x007f) 
    u32(127#0x0000007f)
     s8[-128#0x80]:
    s16(-128#0xff80) 
    s32(-128#0xffffff80)
     u8(128#0x80) 
    u16(65408#0xff80) 
    u32(4294967168#0xffffff80)
     s8[-1#0xff]:
    s16(-1#0xffff) 
    s32(-1#0xffffffff)
     u8(255#0xff) 
    u16(65535#0xffff) 
    u32(4294967295#0xffffffff)
    ######u8Num testing######
     u8[127#0x7f)]
    u16(127#0x007f) 
    u32(127#0x0000007f)
     s8(127#0x7f): 
    s16(127#0x007f) 
    s32(127#0x0000007f)
     u8[128#0x80)]
    u16(128#0x0080) 
    u32(128#0x00000080)
     s8(-128#0x80): 
    s16(128#0x0080) 
    s32(128#0x00000080)
     u8[255#0xff)]
    u16(255#0x00ff) 
    u32(255#0x000000ff)
     s8(-1#0xff): 
    s16(255#0x00ff) 
    s32(255#0x000000ff)
    ######s32Num testing######
    s32[2147483647#0x7fffffff]:
    s16(-1#0xffff) 
     s8(-1#0xff)
    u32(2147483647#0x7fffffff) 
    u16(65535#0xffff) 
     u8(255#0xff)
    s32[-2147483648#0x80000000]:
    s16(0#0x0000) 
     s8(0#0x00)
    u32(2147483648#0x80000000) 
    u16(0#0x0000) 
     u8(0#0x00)
    s32[-1#0xffffffff]:
    s16(-1#0xffff) 
     s8(-1#0xff)
    u32(4294967295#0xffffffff) 
    u16(65535#0xffff) 
     u8(255#0xff)
    ######u32Num testing######
    u32[2147483647#0x7fffffff]
    u16(65535#0xffff) 
     u8(255#0xff)
    s32(2147483647#0x7fffffff): 
    s16(-1#0xffff) 
     s8(-1#0xff)
    u32[2147483648#0x80000000]
    u16(0#0x0000) 
     u8(0#0x00)
    s32(-2147483648#0x80000000): 
    s16(0#0x0000) 
     s8(0#0x00)
    u32[4294967295#0xffffffff]
    u16(65535#0xffff) 
     u8(255#0xff)
    s32(-1#0xffffffff): 
    s16(-1#0xffff) 
     s8(-1#0xff)
    ######s16Num testing######
    s16[32767#0x7fff]: 
    s32(32767#0x00007fff) 
     s8(-1#0xff)
    u16(32767#0x7fff) 
    u32(32767#0x00007fff) 
     u8(255#0xff)
    s16[-32768#0x8000]: 
    s32(-32768#0xffff8000) 
     s8(0#0x00)
    u16(32768#0x8000) 
    u32(4294934528#0xffff8000) 
     u8(0#0x00)
    s16[-1#0xffff]: 
    s32(-1#0xffffffff) 
     s8(-1#0xff)
    u16(65535#0xffff) 
    u32(4294967295#0xffffffff) 
     u8(255#0xff)
    ######u16Num testing######
    u16[32767#0x7fff]:
    u32(32767#0x00007fff) 
     u8(255#0xff)
    s16(32767#0x7fff) 
    s32(32767#0x00007fff) 
     s8(-1#0xff)
    u16[32768#0x8000]:
    u32(32768#0x00008000) 
     u8(0#0x00)
    s16(-32768#0x8000) 
    s32(32768#0x00008000) 
     s8(0#0x00)
    u16[65535#0xffff]:
    u32(65535#0x0000ffff) 
     u8(255#0xff)
    s16(-1#0xffff) 
    s32(65535#0x0000ffff) 
     s8(-1#0xff)
  • 相关阅读:
    HDU 2116 Has the sum exceeded
    HDU 1233 还是畅通工程
    HDU 1234 开门人和关门人
    HDU 1283 最简单的计算机
    HDU 2552 三足鼎立
    HDU 1202 The calculation of GPA
    HDU 1248 寒冰王座
    HDU 1863 畅通工程
    HDU 1879 继续畅通工程
    颜色对话框CColorDialog,字体对话框CFontDialog使用实例
  • 原文地址:https://www.cnblogs.com/jacklikedogs/p/4137376.html
Copyright © 2011-2022 走看看