【问题标题】:Shifting gives a 1 at the most significant digit移位在最高有效数字处给出 1
【发布时间】:2020-06-22 01:50:45
【问题描述】:

我目前正在编写一个 C 函数,该函数从用户那里获取一个数字并将其转换为二进制输出。首先,这是代码:

void Convert_Number_To_Binary(const int num,char *binary) {
    double remainder = num;

    //Start from binary[0] and check if num is divisible by 2^ith power by shifting
    for(int i = 0; i < 33; i++) {
        int shift = num >> i; //shift the current bit value of remainder i bits
        printf("i: %d, %d \n", i,  (shift) );

        //If shift is greater than 0, then remainder is divisible by 2^i
        if( (shift & 1) > 0) {
                binary[32-i] = '1';
        }
        else
                binary[32-i] = '0';
        //printf("i:%d, 32-i:%d\n", i, (32-i));
    }

    //printf("%c, %c", binary[0], binary[31]);

    binary[33] = '\0';
}

代码在大多数情况下都可以正常工作,除了当我输入一个奇数(例如:17)时,我在最重要的位置得到一个:

num = 17    binary = 100000000000000000000000000010001

偶数不出现前导“1”:

num = 16    binary = 000000000000000000000000000010000

我在远程 32 位 linux 机器上运行它,这可能是原因吗?

【问题讨论】:

    标签: c byte-shifting


    【解决方案1】:

    您正在创建一个 33 位而不是 32 位的二进制字符串:

    for(int i = 0; i < 33; i++) {
        int shift = num >> i; //shift the current bit value of remainder i bits
    

    假设 int 是 32 位宽,在循环的最后一次迭代中,您移动的量与您要移动的变量的大小相同。这样做会调用undefined behavior。这在C standard 的第 6.5.7p3 节中记录了有关按位移位运算符的内容:

    对每个操作数执行整数提升。这 结果的类型是提升的左操作数的类型。如果 右操作数的值为负数或大于 或等于提升的左操作数的宽度,行为是 未定义。

    将循环的停止点改为32,并相应调整空终止字节的减法和设置。

    void Convert_Number_To_Binary(const int num,char *binary) {
        //Start from binary[0] and check if num is divisible by 2^ith power by shifting
        for(int i = 0; i < 32; i++) {
            int shift = num >> i; //shift the current bit value of remainder i bits
            printf("i: %d, %d \n", i,  (shift) );
    
            //If shift is greater than 0, then remainder is divisible by 2^i
            if( (shift & 1) > 0) {
                    binary[32-i-1] = '1';
            }
            else
                    binary[32-i-1] = '0';
            //printf("i:%d, 32-i-1:%d\n", i, (32-i-1));
        }
    
        //printf("%c, %c", binary[0], binary[31]);
    
        binary[32] = '\0';
    }
    

    【讨论】:

      【解决方案2】:

      您应该首先将 int 转换为 unsigned int,这将强制 MSB 填充 0。

      类似这样的:

      unsigned int shift = (unsigned int)num >> i;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-25
        • 2020-09-07
        • 2023-03-20
        • 1970-01-01
        相关资源
        最近更新 更多