0

Currently I'm trying to include a library in a C header file. Here is what the original code looks like:

#ifndef SIMULATE_H
#define SIMULATE_H

#ifdef __cplusplus
extern "C" {
#endif

#define RAM_SIZE 16320
#define STRING_SIZE 10
#define BUFFER_SIZE 100
long final_hex[RAM_SIZE];
char zero[STRING_SIZE];
char stringValue[STRING_SIZE];
char buffer[BUFFER_SIZE];
char checksum[BUFFER_SIZE];

#ifdef __cplusplus
}
#endif

#endif /* SIMULATE_H */

What I want to include is "#include <math.h>". It should be very easy, but I have some doubts here:

  1. Does this code mean it can be a header file for both C and C++:

    #ifdef __cplusplus
    extern "C" {
    #endif
    
  2. When I include libraries here, shall I put before the "extern "C"" or after it? Does the order matter for them here?

Toby Zhou
  • 88
  • 10
  • There's no obvious reason why you need to include `` in this header. None of the declarations in the `simulate.h` header themselves require the `` header, so the only reason to include it is because every file that ever includes `simulate.h` will inevitably use at least one declaration or definition from ``. It would be a minor convenience, in other words. Normally, you keep headers minimal as well as self-contained to keep the compile time under control. It might still be sensible, but it isn't obvious that it is sensible. – Jonathan Leffler Sep 07 '17 at 04:35
  • Yes, the code means that the header is intended for use from both C and C++. It's curious though; there are no functions, so it isn't clear that the `extern "C"` is doing anything useful — global variables are not mangled for type-safe linkage. – Jonathan Leffler Sep 07 '17 at 04:38
  • Please clarify your 'add on'. If the code in `simulate.c` is calling a function declared in ``, then the C source should include ``, not the header. You should only include other headers that are necessary to make the outer header (here, `simulate.h`) usable by other source files. Anything that's needed only by `simulate.c` should only be included directly by `simulate.c`. If you had a function `extern void dump_simulation(FILE *fp, const char *tag, const SimulationState *sim_state);` in `simulate.c`, then you'd need to include `` to get the declaration for `FILE`. – Jonathan Leffler Sep 07 '17 at 04:43
  • @JonathanLeffler sorry I didn't make it clear, the reason I want to include is that I'm using a function from in file "simulate.c", which includes "simulate.h". So in this case, shall I include it in "simulate.c" instead of "simulate.h" as you mentioned "self-contained"? – Toby Zhou Sep 07 '17 at 04:43
  • Otherwise, though, you don't need `` in the header. Normally, there would be some functions declared by the header. You should aim to minimize the number of global variables. – Jonathan Leffler Sep 07 '17 at 04:44
  • Yes; only have the `#include ` in `simulate.c` and not in `simulate.h`. – Jonathan Leffler Sep 07 '17 at 04:44
  • @JonathanLeffler oh, I see. thank you for the explanations!! Will edit them accordingly. – Toby Zhou Sep 07 '17 at 04:45

3 Answers3

3

I'm going to focus on another aspect of this code:

long final_hex[RAM_SIZE];

Global data structures need to be defined as extern in header files. Otherwise, each source file which includes the header will try to define its own copy of the structure, which will result in an error at link time (probably something along the lines of "multiple definitions of symbol final_hex").

2

First of all, you probably meant #include not #define .

extern "C" makes a function-name in C++ have 'C' linkage

If you inspect math.h you'll see that it has it's own

#ifdef __cplusplus
extern "C" {
#endif
//...
#ifdef __cplusplus
}
#endif

sections. It is better not to include external headers inside your extern "C" section.

Here is a good basic explanation about includes, but with regards to your example:

  • there is no difference currently if you include before or after your extern "C" section as you are not using anything out of it in the header
  • should you use something of external header, you should include it on top, before usage, otherwise you will get an error
  • if you are not planning to use any defines or types out of math.h, nesting include is not necessary and creates useless dependency, which doesn't matter while project is small, but increases build times in large projects - you should rather include those files separately on top of you source file
isp-zax
  • 3,833
  • 13
  • 21
  • sorry for the typo, I meant "#include". thank you for the links and explanations! In this case, I will try to put the includes before the extern "c" section. For the third part you mentioned "if you are not planning to use any defines or types out of math.h", do you mean calling functions or using variables from math.h? If yes, I'm calling a function from math.h, but it's in the "simulate.c" file. Sorry didn't make it clear in the question. – Toby Zhou Sep 07 '17 at 04:33
  • It seems I should include the library in source file "simulate.c" instead of "simulate.h". Thank you for helping me!! – Toby Zhou Sep 07 '17 at 04:53
  • @Toby Zhou, Yes, unless you use data structures or defines from math.h inside the header, you should rather include it in the source file, simulate.c in this case. – isp-zax Sep 08 '17 at 06:20
2

I don't have the reputation to add a comment but I'm curious if you mean you want to add

#include <math.h>

rather than

#define <math.h>

I'll assume that you you meant #include

You include other libraries like math.h when you need to use something defined in that library such as a function or structure.

The preprocessor, when it comes to the #include statement will replace the #include line with the contents of the math.h file.

You should only include a header file when something in your file references something in the header file. The header file that you have posted the code for does not, as far as I can see, make reference to anything in math.h so you should not include it in that file.

Instead you should have your source file (*.c) that uses declarations in the simulate.h file and presumably math.h include both of those files.

#include "simulate.h"
#include <math.h>

int main(void) {
    double root = sqrt(25.0); /* from math.h */
    int n = STRING_SIZE;      /* from simulate.h */
}

As far as your first question is concerned, the #ifdef _cplusplus is just a conditional compilation directive to the preprocessor. If the variable _cplusplus is defined (using a C++ compiler) then it will add the code between the #ifdef / #endif segment; otherwise it will not.

If you do include the math.h file in the simulate.h file then its location shouldn't matter as far as I'm aware assuming that you don't later make reference in simulate.h to something in math.h before #include <math.h>

  • Sorry for the typo and didn't make it clear. Yes, I'm using in "simulate.c", which includes "simulate.h". Will include in source file "simulate.c" instead. Thank you!! – Toby Zhou Sep 07 '17 at 04:51