tags:

views:

431

answers:

5

I am trying to program using C to write binary data to a .bin file and just iterate through to write from 0000 to FFFF. I figured I would use fopen with a 'wb' tag and then be able to write binary data but I'm unsure how to iterate from 0000 to FFFF using C. Thanks for any help.

Here's my code now:

#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();
}

This will output 00 00 01 00 02 00 ...

Here's my question now. Isn't this supposed to read out 00 00 00 01 00 02...Shouldn't there be an extra '00' at the beginning?

Also, I've been trying to see how could I copy it and extend it therefore making it 0000 0000 0001 0001 etc? [Update: I just copied the fwrite line and did it again and it solved this problem]

+2  A: 

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

kusma
for(unsigned short i = 0;...)
AlexKR
Using `<` will miss out `0xFFFF`. Be careful using `unsigned short` and `i <= 0xFFFF` though, as `i` will always match the condition and your loop will continue forever (`0xFFFF + 1 = 0`).
Paul Stephenson
AlexKR: That's C++, not C ;)Paul: Indeed, corrected.
kusma
Good point, but there is no reason to use a 16bit iterator, it is only important to write 16 bits at a time.
Ofir
This kind of lacks a type for the i variable.
unwind
@Paul Stephenson: Wrote almost exactly the same comment, now deleted :)
Binary Worrier
If `i` is 16-bit, this would be an infinite loop (0xFFFF++ wraps around to 0). So `i` must be at least 32-bit!
AndiDog
The rest is left as an exercise for the reader ;)
kusma
+5  A: 

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

Ofir
Make sure the type of `i` is bigger than an `unsigned short` (e.g. `int` or `unsigned int`). When you come to write it out to your binary file, you'll have to cast back to `unsigned short`.
Paul Stephenson
Tony - Regarding the edit - wouldn't unsigned short overflow to 0? Plus, I am not sure this would be valid ANSI C.
Ofir
@Ofir: Definitely, the current implementation is an endless loop.
sharptooth
Same thing here. 0xFFFF++ would wrap around to 0, producing an infinite loop.
AndiDog
Assuming a 16-bit short, a short is always less than or equal to 0xFFFF, and `i <= 0xffff` will always evaluate to 1.
David Thornley
I rolled back the edit, it was quite inappropriate.
Hans Passant
@nobugz: `int` will only work on platforms which define it as more than 16 bit. As of the standard, the int type has a minimum of 16 bits, so this solution is not cross-platform.
AndiDog
Actually... Assuming a 16-bit short 0xFFFF is -1 (two's compliment). In which case this loop would never execute. Make sure your counter is unsigned, and either stop short of 0xFFFF and do the last element outside the loop, or ensure that your counter is larger than 16 bits.
Chris
+7  A: 

This is a simple example of writing some binary numbers to a file.

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

Note that the variable i here must be bigger than 16-bit so that it does not wrap around (see my comments on the other answers). The long type guarantees a size of at least 32 bit.

AndiDog
thanks for this. i still ran into some problems. i've edited the original question.
Neil Desai
+2  A: 

To loop from 0 to 0xffff, both inclusive, you do:

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

Now, the first interesting question is, what should be the type of i? In C, an unsigned int is guaranteed to hold values in the range [0, 0xffff], which means that i <= 0xffff will always be true for unsigned int i; if UINT_MAX is 0xffff. so i can't be a type of size smaller or equal to unsigned int. long or unsigned long is the smallest type guaranteed to be able to store 0xffff + 1 portably. So, we need i to be of unsigned long or long type. In C99, you can make things easier by including stdint.h and then using uint32_t type.

The second interesting question is, what do you want to write? Is your file's layout going to be:

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

or do you want to write values to a file using your favorite data type above and then be able to read them back again quickly? For example, if int is 32 bits, and your system is little-endian, writing those values will give you a file such as:

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

If you want the first, you have to make sure you write two bytes per number, in the correct order, and that endian-ness of your OS doesn't affect the output. The easiest way to do so is probably something like this:

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

If you want the second, your life is easier, particularly if you don't care about endian-ness:

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

will write your values so you can read them back on the same system with the same kind of variable.

Alok
A: 

To control the Endianess of your output, you will have to write the bytes (octets) yourself:

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(/*...*/);
}

This is a preferred method when the file must be Big Endian. This will ensure the byte ordering regardless of the processor's endianess. This can be adjusted to output in Little Endican as well.

Thomas Matthews