1

I have a common header file being included in multiple cpp files I then compile to make the .so files of each cpp . But when I execute with the final executable, I am seeing that the common header file is being duplicated in the sense that all statements in that header file are being hit as many times as it has been included in the cpp.

How to avert it?

The common header file is:

    // common.h 
    #ifndef _COMMON_H 
    #define _COMMON_H 

    #include<iostream> 

    int funcC(); 
    const int x = funcC(); 

    #endif // COMMON_H 

The other files are:

    // common.c 
    #include "common.h" 
    #include <iostream> 
    int funcC() { 
        std::cout<<"HI HI HI"<<std::endl; 
        return 2; 
    } 

and

    // main1.c 
    #include "common.h" 

    int main() { 
        return 0; 
    } 

I was expecting it you print "HI Hi Hi" only once, but it's printing twice

  • 1
    You included it twice, so it prints twice. Why exactly were you expecting anything else? If you think the include guard should prevent this, then you are mistaken. C++ uses *separate compilation*, what happens when you compile common.c cannot in principle effect what happens when you compile main1.c and vice versa. – john Jul 20 '23 at 05:10
  • Incidentally is this a question about C or C++? The tag says C++ but your filenames say C. There are differences between the two languages, so you should get straight which one you are asking about. – john Jul 20 '23 at 05:12
  • including twice may be needed at times when there is a function declared in common.h but defined in main.c – sushant sharma Jul 20 '23 at 05:14
  • 1
    I'm not saying that including it twice is wrong, just that if you call a function from a header file, then that function is going to be called as many times as the header file is included. If that is your concern then don't call a function from a header file. – john Jul 20 '23 at 05:16
  • @john, these are c++ files only. – sushant sharma Jul 20 '23 at 05:17
  • OK, got it. I just thought naming them `.c` was a bit strange. – john Jul 20 '23 at 05:17
  • 1
    `const int x = funcC();` that should go into common.c and not the header. In the header you should only write `const int x;` to declare it, but the definition needs to go into the implementation file – Raildex Jul 20 '23 at 05:18
  • @john . Ok. However many times we have to declare global variables in such a common file. Is it the case that the file will be loaded resulting in multiple re-declarations every time? – sushant sharma Jul 20 '23 at 05:19
  • @Raildex You need to write `extern const int x;` in the header file, and `extern const int x = funcC();` in common.c – john Jul 20 '23 at 05:19
  • you should read about how a C program is compiled and linked. That should clear things up. – Raildex Jul 20 '23 at 05:19
  • @sushantsharma You are confusing terminology because `const int x = ...` is **not** a declaration it's a **definition**. This issue is that if you put definitions in header files then they get defined as many times as you include the header file. That's why (as a rule) you should not put definitions in header files only decalrations. – john Jul 20 '23 at 05:21

1 Answers1

4

This is a definition

int x;

This is the corresponding declaration

extern int x;

If you put a definition is a header file and include the header file multiple times, then you will get multiple definitions. Generally speaking that is an error, although there are exceptions. However it's fine to have multiple declarations (as long as they are all the same) so that is why generally speaking you only put declarations in header files.

There is an additional rule in C++ (but not C) that const variables automatically have local scope, (similar to declaring them static). That is why your code above does not result in a multiple definition error, although you do have multiple definitions of x each is local to the translation unit in which it appears. If you removed the const you would get a multiple definition error.

Here then is a possible solution to your problem

// common.h
extern const int x; // this is a declaration

// common.cpp
extern const int x = funcC(); // this is a definition

The strange construct in common.cpp is the way you must define a non-locally scoped constant in C++. const is by default local scope, extern overrides that, and then the initializer = funcC() turns what would otherwise be a declaration into a definition.

john
  • 85,011
  • 4
  • 57
  • 81