1

我决定编写一个二进制转换器,代码小而简单,它需要一个整数,并且应该输出一个 char* 和生成的二进制字符串。

这里的问题似乎是最后一个 sprintf 似乎总是将最后一个前置字符加倍。

例如,如果答案是 1001001,它将打印 11001001,或者如果它应该是 -10,它会打印 --10,后者特别特别,因为它甚至不在循环中。

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

void bin_string( char** buffer ,int num ){

    bool neg = false;

    if ( num < 0 ){
        neg = true;
        num = ~num+1;
    }

    if( num == 0 )
        sprintf( *buffer, "%d", 0 );

    while( num > 0 ){

        int rem = num%2;

        sprintf( *buffer, "%d%s", rem, *buffer );

        printf("iteration: %s rem: %d\n", *buffer, rem );
        num = num/2;
    }

    if( neg )
        sprintf( *buffer, "-%s", *buffer );
}

int main( int argc, char** argv ){

    char* a = malloc( sizeof(char)*64 );
    bin_string( &a, 73 );

    printf("Result %s\n",a ); /* output is 11001001 but should be 1001001*/

    return 0;
}
4

3 回答 3

5

C99 及以后的声明sprintf()是:

    int sprintf(char *restrict s, const char *restrict format, ...);

您违反了restrict该声明的一部分。您正在使用,例如:

sprintf(*buffer, "-%s", *buffer);

这是试图就地修改缓冲区,并且是未定义的行为。你很幸运,你得到了如此近乎理智的结果——或者可能是不幸的。您不能在调用的尾随参数中使用目标缓冲区sprintf()

于 2013-02-18T19:54:36.133 回答
2

我想 sprintf 只是不够聪明,无法将缓冲区插入自身。您可能需要有两个缓冲区并交换它们。

于 2013-02-18T19:53:40.487 回答
2

答案是当你对自身进行调用时,你正在调用未定义sprintf()的行为*buffer。你应该做的是:

void bit_string(char *buf, int n)
{
    int nbits = sizeof(n) * CHAR_BIT;
    int i;
    for (i = 0; i < nbits; i++) {
        buf[i] = '0' + ((n >> (nbits - i - 1)) & 1);
    }
    buf[nbits] = 0;
}

(是的,我还为您考虑了效率、可读性和可移植性——不客气。)

于 2013-02-18T20:06:26.763 回答