【问题标题】:Print an int in binary representation using C使用 C 以二进制表示形式打印 int
【发布时间】:2010-11-04 16:39:52
【问题描述】:

我正在寻找一个函数来允许我打印 int 的二进制表示。到目前为止我所拥有的是;

char *int2bin(int a)
{
 char *str,*tmp;
 int cnt = 31;
 str = (char *) malloc(33); /*32 + 1 , because its a 32 bit bin number*/
 tmp = str;
 while ( cnt > -1 ){
      str[cnt]= '0';
      cnt --;
 }
 cnt = 31;
 while (a > 0){
       if (a%2==1){
           str[cnt] = '1';
        }
      cnt--;
        a = a/2 ;
 }
 return tmp;

}

但是当我打电话时

printf("a %s",int2bin(aMask)) // aMask = 0xFF000000

我得到像这样的输出;

00000000000000000000000000000000000xtpYy(还有一堆未知字符。

这是函数中的缺陷还是我打印了字符数组的地址或其他什么?抱歉,我只是看不出哪里出错了。

NB 代码来自here

编辑:这不是家庭作业仅供参考,我正在尝试用不熟悉的语言调试其他人的图像处理例程。但是,如果它被标记为作业,因为它是一个基本概念,那么公平竞争。

【问题讨论】:

  • 随机字符存在,因为这不会在字符串末尾添加 NUL 字节。 ('\0') 这个字符表示字符串的结尾,否则 printf 会一直查找直到找到,在这种情况下查找未知内存。

标签: c binary integer


【解决方案1】:

您的字符串不是以空值结尾的。确保在字符串末尾添加'\0' 字符;或者,您可以使用calloc 而不是malloc 分配它,这会将返回给您的内存归零。

顺便说一下,这段代码还有其他问题:

  • 使用时,它会在您调用它时分配内存,让调用者负责free()ing 分配的字符串。如果你只是在 printf 调用中调用它,你会泄漏内存。
  • 它对数字进行两次传递,这是不必要的。您可以在一个循环中完成所有操作。

这是您可以使用的替代实现。

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

char *int2bin(unsigned n, char *buf)
{
    #define BITS (sizeof(n) * CHAR_BIT)

    static char static_buf[BITS + 1];
    int i;

    if (buf == NULL)
        buf = static_buf;

    for (i = BITS - 1; i >= 0; --i) {
        buf[i] = (n & 1) ? '1' : '0';
        n >>= 1;
    }

    buf[BITS] = '\0';
    return buf;

    #undef BITS
}

用法:

printf("%s\n", int2bin(0xFF00000000, NULL));

第二个参数是指向要存储结果字符串的缓冲区的指针。如果没有缓冲区,可以传递NULLint2bin 将写入static 缓冲区并返回给你。与原始实现相比,它的优点是调用者不必担心free()ing 返回的字符串。

缺点是只有一个静态缓冲区,因此后续调用将覆盖之前调用的结果。您无法保存多次调用的结果以供以后使用。此外,它不是线程安全的,这意味着如果您以这种方式从不同的线程调用该函数,它们可能会破坏彼此的字符串。如果有可能,您需要传入自己的缓冲区,而不是传递 NULL,如下所示:

char str[33];
int2bin(0xDEADBEEF, str);
puts(str);

【讨论】:

  • 使用静态缓冲区作为返回值不是线程安全的,如果涉及多个调用,也不允许保存结果以供以后使用。
【解决方案2】:

有几点:

int f = 32;
int i = 1;
do{
  str[--f] = i^a?'1':'0';
}while(i<<1);
  • 它高度依赖于平台,但 也许上面的这个想法会让你开始。
  • 为什么不用memset(str, 0, 33)来设置 整个 char 数组为 0?
  • 别忘了释放()!!!字符* 函数调用后的数组!

【讨论】:

    【解决方案3】:

    两件事:

    1. 你把 NUL 字符放在哪里?我看不到设置了'\0' 的地方。
    2. Int 已签名,0xFF000000 将被解释为负值。所以while (a &gt; 0) 会立即为假。

    顺便说一句:里面的 malloc 函数很丑。给 int2bin 提供一个缓冲区怎么样?

    【讨论】:

      【解决方案4】:

      这是另一个更优化的选项,您可以传入分配的缓冲区。确保它的大小正确。

      // buffer must have length >= sizeof(int) + 1
      // Write to the buffer backwards so that the binary representation
      // is in the correct order i.e.  the LSB is on the far right
      // instead of the far left of the printed string
      char *int2bin(int a, char *buffer, int buf_size) {
          buffer += (buf_size - 1);
      
          for (int i = 31; i >= 0; i--) {
              *buffer-- = (a & 1) + '0';
      
              a >>= 1;
          }
      
          return buffer;
      }
      
      #define BUF_SIZE 33
      
      int main() {
          char buffer[BUF_SIZE];
          buffer[BUF_SIZE - 1] = '\0';
      
          int2bin(0xFF000000, buffer, BUF_SIZE - 1);
      
          printf("a = %s", buffer);
      }
      

      【讨论】:

      • 另一个 (恕我直言) 使其更具可读性的代码调整是使用 (a & (1>= 1)验证第 i 位。这样循环体只包含逻辑,不包含更新值所需的任何语句。
      • 这成功了,非常感谢!我现在可以回到这个可怕的调试了!
      • 在比较中需要括号:((a & 1) == 0。否则它总是打印 '1'。我也更喜欢这个:*buffer-- = (a & 1) + ' 0'
      • + '0' 部分有什么作用?
      • @JohnMerlino (a&1) 将检查 a 的最右边字节是否为 1。如果是,则该操作将返回 1。“0”是字母 0 的 ascii 代码,即 48十进制。 '1' 是字母 1 的 ASCII 码,十进制为 49。因此,当最右边的位为 0 时,此加法将评估为 48,打印 0,而当它为 1 时,将评估为 49,打印 1。
      【解决方案5】:

      两个编码为here 的简单版本(经过轻微重新格式化后复制)。

      #include <stdio.h>
      
      /* Print n as a binary number */
      void printbitssimple(int n) 
      {
          unsigned int i;
          i = 1<<(sizeof(n) * 8 - 1);
      
          while (i > 0) 
          {
              if (n & i)
                  printf("1");
              else
                  printf("0");
              i >>= 1;
          }
      }
      
      /* Print n as a binary number */
      void printbits(int n) 
      {
          unsigned int i, step;
      
          if (0 == n)  /* For simplicity's sake, I treat 0 as a special case*/
          {
              printf("0000");
              return;
          }
      
          i = 1<<(sizeof(n) * 8 - 1);
      
          step = -1; /* Only print the relevant digits */
          step >>= 4; /* In groups of 4 */
          while (step >= n) 
          {
              i >>= 4;
              step >>= 4;
          }
      
          /* At this point, i is the smallest power of two larger or equal to n */
          while (i > 0) 
          {
              if (n & i)
                  printf("1");
              else
                  printf("0");
              i >>= 1;
          }
      }
      
      int main(int argc, char *argv[]) 
      {
          int i;
          for (i = 0; i < 32; ++i) 
          {
              printf("%d = ", i);
              //printbitssimple(i);
              printbits(i);
              printf("\n");
          }
      
          return 0;
      }
      

      【讨论】:

        【解决方案6】:

        一些建议:

        • 空终止你的字符串
        • 不要使用幻数
        • 检查malloc()的返回值
        • 不要转换malloc()的返回值
        • 如果您对二进制表示感兴趣,请使用二进制运算而不是算术运算
        • 无需循环两次

        代码如下:

        #include <stdlib.h>
        #include <limits.h>
        
        char * int2bin(int i)
        {
            size_t bits = sizeof(int) * CHAR_BIT;
        
            char * str = malloc(bits + 1);
            if(!str) return NULL;
            str[bits] = 0;
        
            // type punning because signed shift is implementation-defined
            unsigned u = *(unsigned *)&i;
            for(; bits--; u >>= 1)
                str[bits] = u & 1 ? '1' : '0';
        
            return str;
        }
        

        【讨论】:

          【解决方案7】:
          void print_binary(int n) {
              if (n == 0 || n ==1) 
                  cout << n;
              else {
                  print_binary(n >> 1);
                  cout << (n & 0x1);
              }
          }
          

          【讨论】:

          • 抱歉,'cout
          • 问题被标记为 C,而不是 C++。此外,如果 n 为负数,则结果未定义。最后,它不是格式化(C/C++ 本身并不关心格式化),而是缺少的括号必须将两个语句组合为一个(我已经为你添加了它们)。
          【解决方案8】:

          这是一个简单的算法。

          void decimalToBinary (int num) {
          
                  //Initialize mask
                  unsigned int mask = 0x80000000;
                  size_t bits = sizeof(num) * CHAR_BIT;
          
                  for (int count = 0 ;count < bits; count++) {
          
                      //print
                      (mask & num ) ? cout <<"1" : cout <<"0";
          
                      //shift one to the right
                      mask = mask >> 1;
                  }
              }
          

          【讨论】:

            【解决方案9】:
            #include <stdio.h>
            int main(void) {
            
                int a,i,k=1;
                int arr[32]; \\ taken an array of size 32
            
                for(i=0;i <32;i++) 
                {
                    arr[i] = 0;   \\initialised array elements to zero
                }
            
                printf("enter a number\n");
                scanf("%d",&a);  \\get input from the user
            
                for(i = 0;i < 32 ;i++)
                {
                    if(a&k)    \\bit wise and operation
                    {
                        arr[i]=1;
                    }
                    else
                    {
                        arr[i]=0;
                    }
                    k = k<<1; \\left shift by one place evry time
                }
                for(i = 31 ;i >= 0;i--)
                {
                    printf("%d",arr[i]);   \\print the array in reverse
                }
            
                return 0;
            }
            

            【讨论】:

              【解决方案10】:

              //当我们的老师要求我们这样做时,我就是这样做的

              int main (int argc, char *argv[]) {
              
                  int number, i, size, mask; // our input,the counter,sizeofint,out mask
              
                  size = sizeof(int);
                  mask = 1<<(size*8-1);
                  printf("Enter integer: ");
                  scanf("%d", &number);
                  printf("Integer is :\t%d 0x%X\n", number, number);
                  printf("Bin format :\t");
                  for(i=0 ; i<size*8 ;++i ) {
                      if ((i % 4 == 0) && (i != 0))  {
                          printf(" ");
                      }
              
                      printf("%u",number&mask ? 1 : 0);
              
                      number = number<<1;
                  }
                  printf("\n");
              
                  return (0);
              } 
              

              【讨论】:

                【解决方案11】:

                这是我将整数显示为二进制代码的方法,它每 4 位分隔:

                int getal = 32;             /** To determain the value of a bit 2^i , intergers are 32bits long**/
                int binairy[getal];         /** A interger array to put the bits in **/
                int i;                      /** Used in the for loop **/
                for(i = 0; i < 32; i++)
                {
                    binairy[i] = (integer >> (getal - i) - 1) & 1;
                }
                
                int a , counter = 0;
                for(a = 0;a<32;a++)
                {
                    if (counter == 4)
                    {
                        counter = 0;
                        printf(" ");
                    }
                   printf("%i", binairy[a]);
                   teller++;
                }
                

                它可能有点大,但我总是以一种(我希望)每个人都能理解发生了什么的方式来写它。希望这会有所帮助。

                【讨论】:

                • 最后一行的teller需要counter(我转译了让大家看懂)
                【解决方案12】:
                #include<stdio.h>
                //#include<conio.h>  // use this if you are running your code in visual c++,      linux don't 
                                     // have this library. i have used it for getch() to hold the screen for input char.
                
                void showbits(int);
                int main()
                {
                    int no;
                    printf("\nEnter number to convert in binary\n");
                    scanf("%d",&no);
                    showbits(no);
                //  getch();        // used to hold screen... 
                                    // keep code as it is if using gcc. if using windows uncomment #include & getch()
                    return 0;   
                
                }
                void showbits(int n)
                {
                    int i,k,andmask;
                
                    for(i=15;i>=0;i--)
                    {
                        andmask = 1 << i;
                        k = n & andmask;
                
                        k == 0 ? printf("0") : printf("1");
                    }
                
                }
                

                【讨论】:

                  【解决方案13】:

                  对我来说最简单的方法(对于 8 位表示):

                  #include <stdio.h>
                  #include <stdlib.h>
                  #include <math.h>
                  
                  char *intToBinary(int z, int bit_length){
                  
                      int div;
                      int counter = 0;
                      int counter_length = (int)pow(2, bit_length);
                  
                      char *bin_str = calloc(bit_length, sizeof(char));
                  
                      for (int i=counter_length; i > 1; i=i/2, counter++) {
                          div = z % i;
                          div = div / (i / 2);
                          sprintf(&bin_str[counter], "%i", div);
                      }
                  
                      return bin_str;
                  }
                  
                  int main(int argc, const char * argv[]) {
                  
                      for (int i = 0; i < 256; i++) {
                          printf("%s\n", intToBinary(i, 8)); //8bit but you could do 16 bit as well
                      }
                  
                      return 0;
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    这是另一个不需要 char * 的解决方案。

                    #include <stdio.h>
                    #include <stdlib.h>
                    
                    void    print_int(int i)
                    {
                        int j = -1;
                        while (++j < 32)
                            putchar(i & (1 << j) ? '1' : '0');
                        putchar('\n');
                    }
                    
                    int main(void)
                    {
                        int i = -1;
                        while (i < 6)
                            print_int(i++);
                        return (0);
                    }
                    

                    或者在这里以获得更多可读性:

                    #define GRN "\x1B[32;1m"
                    #define NRM "\x1B[0m"
                    
                    void    print_int(int i)
                    {
                        int j = -1;
                        while (++j < 32)
                        {
                            if (i & (1 << j))
                                printf(GRN "1");
                            else
                                printf(NRM "0");
                        }
                        putchar('\n');
                    }
                    

                    这是输出:

                    11111111111111111111111111111111
                    00000000000000000000000000000000
                    10000000000000000000000000000000
                    01000000000000000000000000000000
                    11000000000000000000000000000000
                    00100000000000000000000000000000
                    10100000000000000000000000000000
                    

                    【讨论】:

                      【解决方案15】:
                      #include <stdio.h>
                      
                      #define BITS_SIZE 8
                      
                      void
                      int2Bin ( int a )
                      {
                        int i = BITS_SIZE - 1;
                      
                         /*
                          * Tests each bit and prints; starts with 
                          * the MSB
                          */
                        for ( i; i >= 0; i-- )
                        {
                          ( a & 1 << i ) ?  printf ( "1" ) : printf ( "0" );
                        }
                        return;
                      }
                      
                      int
                      main ()
                      {
                        int d = 5;
                      
                        printf ( "Decinal: %d\n", d );
                        printf ( "Binary: " );
                        int2Bin ( d );
                        printf ( "\n" );
                      
                        return 0;
                      }
                      

                      【讨论】:

                        【解决方案16】:

                        没有那么优雅,但完成了你的目标,而且很容易理解:

                        #include<stdio.h>
                        
                        int binario(int x, int bits)
                        {
                            int matriz[bits];
                            int resto=0,i=0;
                            float rest =0.0 ;
                            for(int i=0;i<8;i++)
                            {
                                resto = x/2;
                                rest = x%2;
                                x = resto;
                                if (rest>0)
                                {
                                    matriz[i]=1;
                                }
                                else matriz[i]=0;
                            }
                            for(int j=bits-1;j>=0;j--)
                            {
                                printf("%d",matriz[j]);
                            }
                            printf("\n");
                        }
                        int main()
                        {
                            int num,bits;
                            bits = 8;
                            for (int i = 0; i < 256; i++)
                            {
                                num = binario(i,bits);
                            }
                            return 0;
                        }
                        

                        【讨论】:

                          【解决方案17】:

                          这是我的解决方案。它创建一个掩码,从最左边的所有 0 和一个 1 开始,并为 假定 32 位整数中的每个位在逻辑上将其右移。通过将当前屏蔽的整数的值转换为布尔值来顺序打印这些位。

                          void printBits(int val){
                              for(unsigned int mask = 0x80000000; mask; mask >>= 1){
                                   printf("%d", !!(mask & val));
                              }
                          }
                          

                          【讨论】:

                            【解决方案18】:

                            只是对@Adam Markowitz 答案的增强

                            要让函数支持 uint8 uint16 uint32 和 uint64:

                            #include <inttypes.h>
                            #include <stdint.h>
                            #include <stdio.h>
                            #include <string.h>
                            
                            // Convert integer number to binary representation.
                            // The buffer must have bits bytes length.
                            void int2bin(uint64_t number, uint8_t *buffer, int bits) {
                              memset(buffer, '0', bits);
                              buffer += bits - 1;
                              for (int i = bits - 1; i >= 0; i--) {
                                *buffer-- = (number & 1) + '0';
                                number >>= 1;
                              }
                            }
                            
                            int main(int argc, char *argv[]) {
                              char buffer[65];
                              buffer[8] = '\0';
                              int2bin(1234567890123, buffer, 8);
                              printf("1234567890123 in  8 bits: %s\n", buffer);
                              buffer[16] = '\0';
                              int2bin(1234567890123, buffer, 16);
                              printf("1234567890123 in 16 bits: %s\n", buffer);
                              buffer[32] = '\0';
                              int2bin(1234567890123, buffer, 32);
                              printf("1234567890123 in 32 bits: %s\n", buffer);
                              buffer[64] = '\0';
                              int2bin(1234567890123, buffer, 64);
                              printf("1234567890123 in 64 bits: %s\n", buffer);
                              return 0;
                            }
                            

                            输出:

                            1234567890123 in  8 bits: 11001011
                            1234567890123 in 16 bits: 0000010011001011
                            1234567890123 in 32 bits: 01110001111110110000010011001011
                            1234567890123 in 64 bits: 0000000000000000000000010001111101110001111110110000010011001011
                            

                            【讨论】:

                              猜你喜欢
                              • 2016-04-17
                              • 1970-01-01
                              • 2018-06-15
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2014-06-01
                              • 2013-08-22
                              • 2016-12-13
                              相关资源
                              最近更新 更多