C,使用printf时的奇怪行为

时间:2013-04-12 13:58:22

标签: c binary

这里我得到了一个以二进制表示法打印整数的代码

#define BUF_SIZE 33
int main() {
    for (int count = 0; count <=25; count++){

        char buffer[BUF_SIZE];
        buffer[BUF_SIZE - 1] = '\0';

        int2bin(count, buffer, BUF_SIZE - 1);
        printf("%d = %s \n",count, buffer);
    }
}

char *int2bin(int a, char *buffer, int buf_size) {
    buffer += (buf_size - 1);

    for (int i = 31; i >= 0; i--) {
        buffer--;
        *buffer = (a & 1) + '0';
        a >>= 1;
    }

    return buffer;
}

它很有用,直到我试图挤出一些代码行替换

int2bin(count, buffer, BUF_SIZE - 1);
printf("%d = %s \n",count, buffer);

printf("%d = %s \n",count, int2bin(count, buffer, BUF_SIZE - 1));

这些日志完全破坏了我的输出:

805306368 = 00000000000000000000000000000000
805306369 = 00000000000000000000000000000001
805306370 = 00000000000000000000000000000010
805306371 = 00000000000000000000000000000011
805306372 = 00000000000000000000000000000100
805306373 = 00000000000000000000000000000101

依旧......

你可以解释一下为什么会这样吗?

6 个答案:

答案 0 :(得分:4)

乍一看,-1中的第一个int2bin()看起来不是必需的(因为循环开始时为-1)

请参阅Scott Mermelstein的答案以获得解释

答案 1 :(得分:4)

首先,可以肯定的是,问题不在于printf。 让我们假设printf工作正常。然后结论是你传递了不同的输入。使用它,让我们详细了解您正在做的事情。

在你的两行示例中,它可以工作,因为你传入了缓冲区。可能是在你的单行示例中,你传递的地址不是缓冲区吗?

好吧,在int2bin中,你添加buf_size - 1,然后按照32(从31到0)包含数字,然后应该返回buffer,对吗?

错误。

你将BUF_SIZE - 1传递给int2bin,即32,然后你从中减去1,所以你要加31而不是32,因此不会返回缓冲区。

简单的观察方法:在开始时打印出缓冲区的地址,在函数末尾打印缓冲区的地址。

简单修复:

  • 您可以将第一行int2bin设置为buffer += BUF_SIZE - 1
  • 您只需保存buffer的原始值并返回
  • 即可
  • 您不能在for循环中使用看似随意的硬编码,而是设置i = buf_size

基本上,epatel的第一眼回答是正确的。我的回答只是提供了更多细节。

答案 2 :(得分:3)

int2bin

,用<0>覆盖缓冲区之前的字节。编译器在这个地方为printf奠定了参数“ count ”。

只需在通话中删除“-1”

即可
printf("%d = %s \n",count, int2bin(count, buffer, BUF_SIZE));

由805306368是二进制

00110000 00000000 00000000 00000000

00110000 = 48 ='0'

您的代码中还有其他缺陷,循环计数取决于buf_size!我会建议用这种方式重写它。

#define BUF_SIZE sizeof(int)
int main() {
  for (int count = 0; count <=25; count++){

    char buffer[BUF_SIZE + 1];
    buffer[BUF_SIZE] = '\0';

    int2bin(count, buffer, BUF_SIZE);
    printf("%d = %s \n",count, buffer);
  }
}

char *int2bin(int a, char *pBuffer, int buf_size) {
   char *buffer = pBuffer + buf_size;

   for (int i = buf_size; i > 0; i--) { // loop count depends on buf_size!!!
     buffer--;
     *buffer = (a & 1) + '0';
     a >>= 1;
   }

   return pBuffer;
}

答案 3 :(得分:2)

您必须将该功能称为

int2bin(count, buffer, BUF_SIZE)

否则该函数会从buffer minus 1byte写入位字符(这是一个在内存中存在垃圾的下溢)到buffer + 31 bytes

答案 4 :(得分:1)

你的代码相当模糊,包括计数循环和“试图变聪明”,例如可疑的*buffer = (a & 1) + '0';。位掩码与ASCII编号无关,因此不要在同一操作中混合它们。尝试使代码简单而不是复杂。这是你问题的真正根源。

以更易读的方式重写代码,您的错误就会消失。

#include <stdio.h>
#include <stdint.h>

void int_to_bin (char bin[32+1], uint32_t val)
{
  for(int i=0; i<32; i++)
  {
    uint32_t mask = 1 << (32 - 1 - i); // -1 to compensate for zero indexing

    if( (val & mask) != 0)
    {
      bin[i] = '1';
    }
    else
    {
      bin[i] = '0';
    }
  }

  bin[32] = '\0';
}



int main()
{
  char buf[32+1]; 

  int_to_bin(buf, 0xAAAA);
  puts(buf);
  int_to_bin(buf, 0xCAFEBABE);
  puts(buf);
  int_to_bin(buf, 0x12345678);
  puts(buf);
}

答案 5 :(得分:0)

除了buffer_size可能出错之外(其他答案已经详细解释了)。最简单的解决方法是添加

#include <stdio.h>

char * int2bin(int a, char * buffer, int buf_size);

到代码的顶部。这确实使它编译和放大为我工作。两者都用

int2bin(count, buffer, BUF_SIZE - 1);
printf("%d = %s \n",count, buffer);

printf("%d = %s \n", count, int2bin(count, buffer, BUF_SIZE));