繁体   English   中英

C,使用printf时的奇怪行为

[英]C, strange behavior while using printf

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

#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

等等...

你能解释一下为什么吗?

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

请参阅Scott Mermelstein的答案进行解释

首先,可以肯定的是,问题不在于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的第一眼回答是正确的。 我的回答只是提供了更多细节。

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;
}

你必须把这个函数称为

int2bin(count, buffer, BUF_SIZE)

否则该函数将从buffer minus 1byte (这是一个下溢,在内存中放置一些垃圾)写入bit-chars到buffer minus 1byte buffer + 31 bytes

你的代码相当模糊,包括计数循环和“试图变聪明”,例如fishy *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);
}

除了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));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM