How to dump a binary file as a C/C++ string literal?

xxd has a mode for this. The -i/--include option will:

output in C include file style. A complete static array definition is written (named after the input file), unless xxd reads from stdin.

You can dump that into a file to be #included, and then just access foo like any other character array (or link it in). It also includes a declaration of the length of the array.

The output is wrapped to 80 bytes and looks essentially like what you might write by hand:

$ xxd --include foo
unsigned char foo[] = {
  0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
  0x21, 0x0a, 0x0a, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x76, 0x65,
  0x72, 0x79, 0x20, 0x63, 0x75, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x21, 0x20,
  0x57, 0x65, 0x6c, 0x6c, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x0a
};
unsigned int foo_len = 47;

xxd is, somewhat oddly, part of the vim distribution, so you likely have it already. If not, that's where you get it — you can also build the tool on its own out of the vim source.


You can almost do what you want with hexdump, but I can't figure out how to get quotes & single backslashes into the format string. So I do a little post-processing with sed. As a bonus, I've also indented each line by 4 spaces. :)

hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/.*/    "&"/'

Edit

As Cengiz Can pointed out, the above command line doesn't cope well with short data lines. So here's a new improved version:

hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x  //g; s/.*/    "&"/'

As Malvineous mentions in the comments, we also need to pass the -v verbose option to hexdump to prevent it from abbreviating long runs of identical bytes to *.

hexdump -v -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x  //g; s/.*/    "&"/'

xxd is good but the result is highly verbose and takes a lot of storage space.

You can achieve practically the same thing using objcopy; e.g.

objcopy --input binary \
    --output elf32-i386 \
    --binary-architecture i386 foo foo.o

Then link foo.o to your program and simply use the following symbols:

00000550 D _binary_foo_end
00000550 A _binary_foo_size 
00000000 D _binary_foo_start

This is not a string literal, but it's essentially the same thing as what a string literal turns into during compilation (consider that string literals do not in fact exist at run-time; indeed, none of the other answers actually give you a string literal even at compile-time) and can be accessed in largely the same way:

unsigned char* ptr = _binary_foo_start;
int i;
for (i = 0; i < _binary_foo_size; i++, ptr++)
   putc(*ptr);

The downside is that you need to specify your target architecture to make the object file compatible, and this may not be trivial in your build system.

Tags:

C

Hexdump

Xxd