二进制0000到FFFF使用C.

时间:2010-02-01 14:10:06

标签: c binary

我正在尝试使用C编程将二进制数据写入.bin文件,然后迭代以从0000写入FFFF。我想我会使用带有'wb'标签的fopen,然后能够写二进制数据,但我不确定如何使用C从0000迭代到FFFF。感谢您的帮助。

现在是我的代码:

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

int main()
{
 FILE *f = fopen("binary.bin", "wb");
 unsigned long i;

 //if(f == NULL) { ...error handling... }

 for(i = 0x0000; i <= 0xFFFF; i++){
  // Write something to the file, e.g. the 16-bit (2 byte) value of "i"
  unsigned short someData = i;
  fwrite(&someData, 1, 2, f);
 }

 fclose(f);
 return 0;
 //printf("Hello World\n");
 getchar();
}

这将输出00 00 01 00 02 00 ...

现在是我的问题。难道这不应该读出00 00 00 01 00 02 ......开头不应该有额外的'00'吗?

另外,我一直试图看看如何复制它并扩展它因此使其成为0000 0000 0001 0001等? [更新:我刚刚复制了fwrite行并再次执行了它并解决了这个问题]

6 个答案:

答案 0 :(得分:8)

这是将一些二进制数写入文件的简单示例。

FILE *f = fopen("yourfile", "wb");

if(f == NULL) { ...error handling... }

for(unsigned long i = 0x0000; i <= 0xFFFF; ++i)
{
    // Write something to the file, e.g. the 16-bit (2 byte) value of "i"
    unsigned short someData = i;
    fwrite(&someData, 1, 2, f);
}

fclose(f);

请注意,此处的变量i必须大于16位,以便它不会环绕(请参阅我对其他答案的评论)。 long类型保证大小至少为32位。

答案 1 :(得分:5)

for (int i = 0x0000; i <= 0xffff; ++i)

答案 2 :(得分:3)

要从0循环到0xffff,请执行以下操作:

for (i=0; i <= 0xffff; ++i)

现在,第一个有趣的问题是,i的类型应该是什么?在C中,unsigned int保证保留[0, 0xffff]范围内的值,这意味着如果i <= 0xffff为{unsigned int i;UINT_MAX将始终为真0xffff 1}}。因此i不能是小于或等于unsigned int的大小。 longunsigned long是保证能够轻松存储0xffff + 1的最小类型。因此,我们需要iunsigned longlong类型。在C99中,您可以通过添加stdint.h然后使用uint32_t类型来简化操作。

第二个有趣的问题是,你想写什么?您的文件布局是否为:

00 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07
...
FF F8 FF F9 FF FA FF FB FF FC FF FD FF FE FF FF

或者您是否想使用上面您喜欢的数据类型将值写入文件,然后能够快速再次阅读它们?例如,如果int是32位,并且您的系统是little-endian,那么编写这些值将为您提供如下文件:

00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ...

如果你想要第一个,你必须确保按正确的顺序为每个数字写两个字节,并且操作系统的那个字节序不会影响输出。最简单的方法可能是这样的:

for (i=0; i <= 0xff; ++i) {
    unsigned char values[2];
    values[0] = (i & 0xff00) >> 8;
    values[1] = i & 0xff; 
    fwrite(values, 1, 2, fp); 
}

如果你想要第二种,你的生活会更容易,特别是如果你不关心这种情况:

for (i=0; i <= 0xff; ++i) {
    fwrite(&i, sizeof i, 1, fp);
}

将写入您的值,以便您可以使用相同类型的变量在同一系统上读取它们。

答案 3 :(得分:2)

for (i = 0x0000; i <= 0xFFFF; ++i)

答案 4 :(得分:0)

要控制输出的 Endianess ,您必须自己编写字节(八位字节):

for (unsigned int i = 0; // Same as 0x0000
     i <= 0xFFFF;
     ++i)
{
  unsigned char c;
  c = i / 256; // In Big Endian, output the Most Significant Byte (MSB) first.
  fputc(/*...*/);
  c = i % 256;
  fputc(/*...*/);
}

当文件必须是Big Endian时,这是首选方法。无论处理器的字节顺序如何,这都将确保字节顺序。这可以调整为Little Endican的输出。

答案 5 :(得分:0)

以大端方式可移植地写入字节的替代方法:查看htonshtonl(以及它们的反转)。

这些转换为您的机器使用的任何格式(英特尔芯片是小端,正如几个人所指出的)到“网络”顺序(大端)。 htons用16位字表示; {32}中的htonl。另外一个好处是,如果您的程序在Big Endian机器上,那么这些程序将编译为no-ops。它们在<arpa/inet.h><netinet/in.h>中定义,具体取决于系统。

BSD(和Linux)还在htobe16中提供了一组名为<endian.h>(大端16位主机)的例程。

这些也有助于节省一次写入一个字节的开销。

如果你想要自己提取高字节/低字节,你可能也应该使用位屏蔽来完成它。您的编译器可能足够聪明,可以将divide / modulo转换为位掩码,但如果不是,则会有令人遗憾的性能(除法)。

{
  unsigned int x = 0xdead;
  unsigned char hi = (x & 0xff00) >> 8;
  unsigned char lo = (x & 0x00ff);
}
{
  unsigned long int x = 0xdeadbeef;
  unsigned char by0 = (x & 0xff000000) >> 24;
  unsigned char by1 = (x & 0x00ff0000) >> 16;
  unsigned char by2 = (x & 0x0000ff00) >> 8;
  unsigned char by3 = (x & 0x000000ff);
}

gcc看起来很聪明,可以在分区之外进行优化,但是很好。)