8

I'd like to include in na single static C program a bunch of data (say, images, but also other data, embedded in executable since I'm working on an embedded platform without files).

Thus, I wrote a little img2c creating const data from my data files, creating a file with static const arrays initializers to be put to flash (using C99 nice features)

My question is, should I put them in a .h file, like I've seen many times - by example gimp can save as .h files, not .c files - or in a .c file, referenced in a header with just the const extern declaration for further references, without having to include all data and pass it all to the compiler, and redeclare it each time I use it ?

Preprocessor macros are out of the question, since I'll reference their address, not include the whole data each time.

makapuf
  • 1,370
  • 1
  • 13
  • 23
  • As an aside GIMP can save to C source files as well as headers. It's under File->Save As and change the file type to C source code. – tinman Aug 09 '12 at 13:11
  • yes, of course. my remark was more that, by default, it saves to .h which seems counterintuitive. – makapuf Aug 09 '12 at 23:17

4 Answers4

6

If you put the data in a header every compilation unit that pulls in that header will get its own copy of the data. Imagine two .c files that each go to a .o. Each .o will have a copy of the data and your final executable can be bigger than it needs to be.

If you put it in a .c and extern it in a header, only the one .o will contain the data and your final executable can be smaller. Also, if you change things the recompile can be quicker if it's just a change to a single .c rather than all the .c files that include your header.

As you noted, you may also run into problems with the linker, as symbols will be defined multiple times, see the answers to Repeated Multiple Definition Errors from including same header in multiple cpps. It's going to be better all around to put an extern in the header and the data in a .c

Community
  • 1
  • 1
Paul Rubel
  • 26,632
  • 7
  • 60
  • 80
4

Header files in C are nothing special; the .h extension won't change how the compiler handles them. It's more of a hint for humans "this file probably doesn't contain any code".

So if you put actual binary data in there, the compiler will create a copy of the array in each file in which you include the header (instead of simply adding a reference to a shared global array).

GIMP creates a header file because it doesn't know how you plan to use the data. The idea is that you'll include this header file exactly once in a .c file which then processes the data in some way. If it wrote a .c file and you made changes to the code, GIMP would have to merge the changes when you ask it to update the data - it would be messy.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
3

As with everything in C, there is some debate as to best practice here. Common practice is to put the actual values in your implementation (.c) and the declarations (extern something something) in the header (.h). That way, you can update the values without having to recompile every file that includes the header.

The answer is almost never "redeclare it each time I use it."

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
2

This can be done by making sure that the variable is only defined in a single source file. For this a little preprocessor "programing" is needed.

Header file:

/* Standard include guard */
#ifndef X_H
#define X_H

#ifdef X_SOURCE
uint8_t data[] = { /* ... */ };
#else
extern uint8_t data[];
#endif

#endif  /* End of include guard */

Source file:

#define X_SOURCE
#include "x.h"

/* ... */

All other source files just need to include the file "x.h" and they can reference data.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • While this works, there is a drawback: If the array is big, at least the preprocessor will have to parse it -> it will slow down the compiler. – Aaron Digulla Aug 09 '12 at 13:12
  • @AaronDigulla, preprocessor performance is almost never an issue these days, I can assure you. And here it is code that is inside `#if` conditionals. Such lines can (and are!) just skiped in looking at the first non-blank character for a `#`. – Jens Gustedt Aug 09 '12 at 13:43