【问题标题】:How to fprintf an int to binary in C?如何在C中将int转换为二进制?
【发布时间】:2019-02-28 04:59:22
【问题描述】:

我正在尝试将 16 位有符号整数的二进制数写入文件。我搜索了很多,当然我发现了许多将整数变量转换为二进制的示例。但在我的情况下,这些函数效率不高,因为我需要转换 50e6 个样本/秒。调用一个函数来转换每个样本需要大量的计算时间。

所以我想做的是:

int array[] = {233, 431, 1024, ...}
for (i = 0; i < sizeof(array); i++){
    fprintf(outfile, "%any_binary_format \n", array[i]);
}

文件中的结果应该是:

0000000011101001
0000000110101111
0000010000000000

【问题讨论】:

  • 这种格式不存在。您必须编写自己的函数。
  • 没有标准的说明符来实现这一点。你必须自己写。
  • 当你说你要写16位0000000011101001时,你想写成16字节、4字节还是2字节? (我猜是 2,但前面三个 cmets 都假定为 16。)
  • 不清楚你是否理解二进制文件和ASCII字符串'1''0'数字之间的区别。您的“文件中的结果应该是”不明确。如果性能问题,您需要二进制 - 即每个样本 2 个字节,而不是 16 个 ASCII 数字和换行符。这可能是您的意思,但正如@SteveSummit 所指出的那样,其他人并没有以这种方式解释它。
  • 在您的循环中,您很可能会越界访问array

标签: c types binary format


【解决方案1】:

fprintf 用于格式化输出 - 格式化是“人类可读”文本,因此如果您想要二进制输出,则不适合使用它。为此,您应该使用fwrite():

for (i = 0; i < sizeof(array) / sizeof(*array); i++ )
{
    fwrite (&array[i], sizeof(*array), 1, outfile ) ;
}

注意我还修复了循环终止,以正确迭代数组中的元素数。但实际上循环是不必要的——输出是二进制的,数组是二进制的——你可以这样输出整个数组:

fwrite( array, sizeof(array), 1, outfile ) ;

您的 50Msps 性能要求将需要维持大约 95Mb/s 的写入性能 - 这要求很多,而且不可能通过一次写入一个样本来实现。使用内存映射文件可能会更好,但除非您使用实时操作系统,否则无法保证您将无限期维持该输出速率 - 只需要一些其他进程来访问驱动器,并且可能会引入无法接受的延迟。

另请注意,必须为 二进制 输出打开文件 - 特别是在 Windows 上,以防止将 CR 转换为 CR+LF,这将对您的示例数据造成灾难性影响。

【讨论】:

    【解决方案2】:

    如果你想使用 printf,你可以使用这样的东西:

    #define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c\n"
    #define BYTE_TO_BINARY(byte)  \
      (byte & 0x80 ? '1' : '0'), \
      (byte & 0x40 ? '1' : '0'), \
      (byte & 0x20 ? '1' : '0'), \
      (byte & 0x10 ? '1' : '0'), \
      (byte & 0x08 ? '1' : '0'), \
      (byte & 0x04 ? '1' : '0'), \
      (byte & 0x02 ? '1' : '0'), \
      (byte & 0x01 ? '1' : '0')
    
    int main()
    {
       uint8_t value = 5;  
       printf(BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(value));
       return 0;
    }
    

    应该打印 00000101。我有时在嵌入式代码中使用它来调试检查寄存器值。如果要将 ascii 二进制字符串写入文件,只需将 printf 替换为 fprintf。

    【讨论】:

    • 虽然这似乎是他所要求的,但考虑到性能要求,这似乎不太可能是他的意图。它也不会生成 binary 文件;而是一个仅包含 0x31 和 0x30 字符值的文本文件。
    【解决方案3】:

    如果您的编译器支持内联,则无需担心小函数的开销,请查看this。 无论如何,您可以简单地将函数实现为宏。 如果您想要更快的方法,您可以使用更大的缓冲区(更快的运行时间的大小取决于机器),例如 char str[1

    #define SHORT_WIDTH 16
    #define TEST 1
    #define PADDING 1 /* set to 0 if you don't need the leading 0s */
    
    char *ShortToBin(unsigned short x, char *buffer) {
        #if PADDING
            int i;
            for(i = 0; i < SHORT_WIDTH; ++i)
                buffer[SHORT_WIDTH - i - 1] = '0' + ((x >> i) & 1);
            return buffer;
        #else
            char *ptr = buffer + SHORT_WIDTH;
            do {
                *(--ptr) = '0' + (x & 1);
                x >>= 1;
            } while(x);
            return ptr;
        #endif
    }
    
    #if TEST
        #include <stdio.h>
        
        int main() {
            short n;
            char str[SHORT_WIDTH+1]; str[SHORT_WIDTH]='\0';
            while(scanf("%hd", &n) == 1)
                puts(ShortToBin(n, str));
            return 0;   
        }
    #endif
    

    【讨论】:

      猜你喜欢
      • 2019-03-18
      • 2018-02-04
      • 1970-01-01
      • 2016-07-13
      • 1970-01-01
      • 1970-01-01
      • 2020-08-29
      • 2014-11-28
      • 1970-01-01
      相关资源
      最近更新 更多