Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C literal constants : in header or C file?

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.

like image 973
makapuf Avatar asked Aug 09 '12 12:08

makapuf


4 Answers

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

like image 156
Paul Rubel Avatar answered Sep 22 '22 00:09

Paul Rubel


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.

like image 42
Aaron Digulla Avatar answered Sep 18 '22 00:09

Aaron Digulla


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."

like image 34
Jonathan Grynspan Avatar answered Sep 21 '22 00:09

Jonathan Grynspan


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.

like image 42
Some programmer dude Avatar answered Sep 19 '22 00:09

Some programmer dude