代码之家  ›  专栏  ›  技术社区  ›  JobHunter69

如何进行符号扩展,然后在C中找到无符号二进制数的值?

c
  •  0
  • JobHunter69  · 技术社区  · 7 年前

    我有一个声明为int的变量

    int a=-3;

    我想把两个补码的值符号扩展到16位。因此,它变为:1111111111111101,然后找到这个数字的无符号值,即65533(我相信)。

    换句话说,我想从-3到65533。

    回答如下: Sign extension from 16 to 32 bits in C 我在第一步就卡住了。以下是我的代码的简化版本:

    #include <stdio.h>
    #include <string.h>
    
    int main () {
        int s = -3;
        printf("%x\n", s);
        s = (int16_t)s;
        printf("%x\n", s);
        int16_t i = s;
        printf("%x\n", i);
    
        return(0);
    }
    

    我使用gcc测试进行编译。c和所有三个printf语句都给出“fffffff d”

    你知道为什么演员阵容不起作用,也许还有更好的解决方案吗?

    4 回复  |  直到 7 年前
        1
  •  2
  •   ikegami Gilles Quénot    7 年前

    您似乎正在努力解决这个问题的地方是,在将位解释为有符号或无符号或精确的宽度类型时,您确切地理解了要处理的位。

    如何对扩展进行签名,然后找到无符号二进制文件的值 C中的数字?

    答复: 你不知道--这些东西永远不会变。。。。

    当您申报时 int a = -3; ,位在内存中设置。此后,除非更改它们,否则它们是完全相同的32位(或其他 sizeof a 在您的硬件上)。

    理解符号扩展的关键是,它仅适用于在2的补码系统下解释负值时,当施法或分配给 较大尺寸 类型否则,您不会扩展任何内容,您只是 口译 将位作为不同的类型。

    我们将用一个简短的例子来说明你的问题。在这里 int a=-3; 声明(定义)和 a 此后永不改变。然而,您可以解释这些位(或者通过失去类比从不同的角度看它们),并将这些位用作 short , unsigned short , int16_t uint16_t 在所有无符号情况下,将其解释为十六进制值,例如。

    #include <stdio.h>
    #include <stdint.h>
    
    #ifdef __GNUC__
    #include <inttypes.h>
    #endif
    
    int main (void) {
    
        int a = -3;
    
        printf ("a (as int)                     : %d\n"
                "a (as short)                   : %hd\n"
                "a (as unsigned short)          : %hu\n"
                "a (as unsigned short hex)      : 0x%0x\n"
                "a (as PRId16)                  : %" PRId16 "\n"
                "a (as PRIu16)                  : %" PRIu16 "\n"
                "a (as PRIx16)                  : 0x%" PRIx16 "\n",
                a, (short)a, (unsigned short)a, (unsigned short)a,
                (int16_t)a, (uint16_t)a, (uint16_t)a);
    
        return 0;
    }
    

    使用/输出示例

    $ ./bin/exact3
    a (as int)                     : -3
    a (as short)                   : -3
    a (as unsigned short)          : 65533
    a (as unsigned short hex)      : 0xfffd
    a (as PRId16)                  : -3
    a (as PRIu16)                  : 65533
    a (as PRIx16)                  : 0xfffd
    

    仔细检查一下,看看所有的答案,如果你还有其他问题,请告诉我们。

        2
  •  1
  •   M.M    7 年前

    您的代码对printf中的参数类型使用了错误的格式说明符,从而导致未定义的行为。

    以下是一些正确的代码:

    #include <stdio.h>
    
    int main(void)
    {
        int s = -3;
        uint16_t u = s;          // u now has the value 65533
    
        printf("%u\n", (unsigned int)u);
        printf("%x\n", (unsigned int)u);
    }
    

    打印F a的代码 uint16_t 有点复杂,转换到 unsigned int 和使用 %u %x 哪些是 无符号整型 .

        3
  •  0
  •   Dash Winterson    7 年前

    FFFFFFF D是两个正确的补码值,它只是用十六进制打印出来的 使用 %d 在printf语句中

    #include <stdio.h>
    #include <string.h>
    
    int main () {
        int s = -3;
        printf("%d\n", s);
        s = (int16_t)s;
        printf("%d\n", s);
        int16_t i = s;
        printf("%d\n", i);
    
        return(0);
    }
    

    你应该看到65533的值

        4
  •  0
  •   tsapelman    7 年前

    在C语言中,将有符号值转换为更宽的类型会自动扩展其符号。 要获取补码值,需要将值强制转换为适当的无符号类型:

        #include <stdio.h>
        #include <stdint.h>
    
        int main ()
        {
            int s = -3;
            printf("%x\n", s);
            int16_t s16 = (int16_t)s;
            printf("%hd\n", s16);
            uint16_t c16 = (uint16_t)s16;
            printf("%hu\n", c16);
        }
    

    我得到的结果是:

        fffffffd
        -3
        65533