二进制转换功能

时间:2019-03-05 00:50:15

标签: c function binary

我正在尝试使用我在下面的C中编写的函数将十进制值转换为二进制。我无法弄清楚为什么它打印32个零而不是二进制值2的原因。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>

int binaryConversion(int num){
    int bin_buffer[32];
    int mask = INT_MIN;
    for(int i = 0; i < 32; i++){
        if(num & mask){
            bin_buffer[i] = 1;
            mask >> 1;
        }
        else{
            bin_buffer[i] = 0;
            mask >> 1;
        }
    }
    for(int j = 0; j < 32; j++){
        printf("%d", bin_buffer[j]);
    }
}


int main(){
    binaryConversion(2);
}

谢谢

4 个答案:

答案 0 :(得分:3)

两个错误:

  1. 您使用>>而不是>>=,因此实际上并没有更改mask
  2. 您没有将mask声明为unsigned,所以当您移位时,它将得到符号扩展,这是您不希望的。

答案 1 :(得分:2)

如果您输入:

printf("%d %d\n", num, mask);

立即在您的for循环中,您会看到原因:

2 -2147483648
2 -2147483648
2 -2147483648
2 -2147483648
:
2 -2147483648

表达式mask >> 1 确实mask的值右移,但实际上并未将其分配回mask。我认为您想要使用:

mask >>= 1;

最重要的是(一旦解决了这个问题),您会发现掩码中的值有些奇怪,因为右移负值可以保留符号,这意味着您将得到设置多个位。

使用无符号整数会更好,因为>>运算符将对它们进行更符合您期望的操作。


此外,将所有这些位写入缓冲区没有什么意义,只是以后可以将它们打印出来。除非您需要对这些位进行一些操作(在这里似乎不是这种情况),否则您可以直接在计算出它们时直接输出它们(并摆脱现在不必要的i变量)。 / p>


因此,考虑到所有这些要点,您可以极大地简化代码,例如使用以下完整程序:

#include <stdio.h>
#include <limits.h>

int binaryConversion(unsigned num) {
    for (unsigned mask = (unsigned)INT_MIN; mask != 0; mask >>= 1)
        putchar((num & mask) ? '1' : '0');
}

int main(void) {
    binaryConversion(2);
    putchar('\n');
}

还有一点需要注意,实际上只需要设置最高位就不需要INT_MIN的值。由于C当前允许处理负数的补码和符号幅度(以及二进制补码),因此INT_MIN可能会设置一个设置了多个位的值(例如-32767)。 / p>

可以采取一些措施来从C中删除这些很少使用的编码(C ++ 20已将其标记出来),但是,为了实现最大的可移植性,您可以选择使用以下功能:

int binaryConversion(unsigned int num) {
    // Done once to set topBit.

    static unsigned topBit = 0;
    if (topBit == 0) {
        topBit = 1;
        while (topBit << 1 != 0) topBit <<= 1;
    }

    // Loop to process all bits.

    for (unsigned mask = topBit; mask != 0; mask >>= 1)
        putchar(num & mask ? '1' : '0');
}

这将在您第一次调用该函数时将高位设置为高,而不考虑负编码的变化情况。只要注意是否在线程程序中同时调用它即可。

但是,如上所述,这可能不是必需的,使用非常粗心/不幸的工业机器操作员的手指上,使用其他两种编码的环境数量是可以计数的。

答案 2 :(得分:1)

您已经回答了有关使用>>而不是=>>的主要问题。但是,从根本上讲,不需要将10缓存在int(例如int bin_buffer[32];)数组中,也不需要使用{ {1}} variadic函数用于显示printf值,如果您要做的只是输出数字的二进制表示形式。

相反,您只需要int来输出putchar()'1',这取决于是否设置了位或将其清除。您还可以通过提供所需的表示形式的大小来使输出功能更有用,例如'0'(8位),byte(16位),等等。

例如,您可以这样做:

word

您可以通过其中设置要显示的位数,例如

使用/输出示例

#include <stdio.h>
#include <limits.h>

/** binary representation of 'v' padded to 'sz' bits.
 *  the padding amount is limited to the number of
 *  bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
 */
void binaryConversion (const unsigned long v, size_t sz)
{
    if (!sz) { fprintf (stderr, "error: invalid sz.\n"); return; }
    if (!v)  { while (sz--) putchar ('0'); return; }

    if (sz > sizeof v * CHAR_BIT)
        sz = sizeof v * CHAR_BIT;

    while (sz--)
        putchar ((v >> sz & 1) ? '1' : '0');
}

int main(){
    fputs ("byte : ", stdout);
    binaryConversion (2, 8);
    fputs ("\nword : ", stdout);
    binaryConversion (2, 16);
    putchar ('\n');
}

您的方法没有什么问题,但是可能会有更简单的方法来获得相同的输出。

如果您还有其他问题,请告诉我。

答案 3 :(得分:0)

INT_MIN是一个负数,因此当您使用>>移到右侧时,最高有效位仍然是1而不是零,最后以{{1 }}所有位的值为mask=11111...111。同样1的值也没有改变。最好改用mask。您可以尝试对>>=进行屏蔽,并像这样将0x1的实际值而不是num移位。

mask