我决定编写一个二进制转换器,代码小而简单,它需要一个整数,并且应该输出一个带有结果二进制字符串的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;
}
答案 0 :(得分:5)
C99及以后的sprintf()
声明是:
int sprintf(char *restrict s, const char *restrict format, ...);
您违反了该声明的restrict
部分。您正在使用,例如:
sprintf(*buffer, "-%s", *buffer);
这是尝试原位修改缓冲区,并且是未定义的行为。你很幸运,你得到了如此近乎理智的结果 - 或者也许是不幸的。您不能在对sprintf()
的调用的尾随参数中使用目标缓冲区。
答案 1 :(得分:2)
我认为sprintf不够聪明,不能将缓冲区插入自身。您可能需要有两个缓冲区并进行交换。
答案 2 :(得分: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;
}
(是的,我也为您提供效率,可读性和便携性 - 欢迎您。)