1

I am currently looking through the code written by senior engineer. The code works fine but i am trying to figure out one detail.

He uses quite a few global variables and his code is broken down into a lot of separate files. So he uses a technique to make sure that global vars are declared everywhere where he needs to access them but are only defined once.

The technique is new to me but I read few articles on the internet and got some understanding about how it works. He uses

#undef EXTERN

followed by conditional definition of EXTERN as an empty string or actual extern. There is a very good article here explaining how it works. Also there is a discussion here

What gets me confused is that all examples I saw on the web suggest to include header file in a regular way in all of the source files that need it except for one. In this single special case line that includes header is preceded by definition of a symbol that will ensure that EXTERN will be defined to an empty string and .. so on (see link above). Typically this single special case is in main or in a separate source file dedicated to the declaration of global variables.

However in the code that I am looking at this special case is always in the source file that corresponds the header. Here is the minimal example:

"peripheral1.h" :

#undef EXTERN
#ifndef PERIPHERAL_1_CPP
#define EXTERN extern
#else
#define EXTERN
#endif

EXTERN void function1(void);

"peripheral1.cpp" :

#define PERIPHERAL_1_CPP
#include "peripheral1.h"

function1()
{
    //function code code here
}

Everywhere else in the code he just does

#include "peripheral1.h"

My question is how and why does that work? In other words, how does compiler know where to define and where to just declare function (or variable, or class ...)? And why is it ok in above example to have the lines :

#define PERIPHERAL_1_CPP
#include "peripheral1.h"

in actual peripheral1.cpp rather then in main.cpp or elsewhere?

Or am I missing something obvious here?

Community
  • 1
  • 1
Art Gertner
  • 292
  • 12
  • 27
  • 1
    I really don't see the point of this. Functions don't need to be declared `extern` and you can declare globals in a header `extern` and then define them in a .cpp file without `extern` without using these preprocessor macros. – Simple Dec 12 '13 at 16:03
  • @Simple, with this "technique", you need to write each variable declaration only once, instead of twice. – chill Dec 12 '13 at 16:13
  • 1
    Sounds like he shouldn't be a senior engineer any more. – Lightness Races in Orbit Dec 12 '13 at 16:41

2 Answers2

2

All the source files, except "perripheral1.cpp", after preprocessing contain a sequence of external variable declarations like:

extern int a;
extern int b;
extern int c;

In peripheral1.cpp only, after preprocessing, there will be a sequence of declarations:

int a;
int b;
int c;
int d;

which are tentative definitions of the corresponding variables, which, under normal circumstances are equivalent of the external definitions :

int a = 0;
int b = 0;
int c = 0;
int d = 0;

End result is, variable are declared everywhere, but defined only once.

PS. To be perfectly clear ...

In other words, how does compiler know where to define and where to just declare function (or variable, or class ...)?

The compiler knows where to declare, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a declaration. The compiler knows where to define, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a definition.

In other other words, the compiler does not know - you tell it explicitly what you want it to do.

chill
  • 16,470
  • 2
  • 40
  • 44
  • thanks for your answer, but it does not answer my question. Please see my comment to Nostalgia's answer above – Art Gertner Dec 12 '13 at 16:31
  • You have described "how". I have answered "why" - because the C Standard defines certain C language constructs (examples above) to be declarations and certain others (examples above) to be definitions. Sorry, if it's not clear enough. – chill Dec 12 '13 at 16:44
  • This is not true. C++ does not have tentative definitions. – Lightness Races in Orbit Aug 13 '18 at 15:28
1

Nostalgia

Ahh, this takes me back a fair way (about 20 years or so).

This is a way for C code to define global variables across multiple files: you define the variable once using a macro to ensure it is defined exactly only once, and then extern it in other C code files so you can utilise it. Nowadays it is quite superfluous in many instances, however it still has its place in legacy code, and will (most likely) still work in many modern compilers, nut it is C code not C++.

Normally the likes of #define PERIPHERAL_1_CPP is utilised to ensure uniquenesss of inclusion like a #pragma once

In my own code I would use something like:

#ifndef PERIPHERAL_1_CPP
#define PERIPHERAL_1_CPP
// my includes here
// my code here
#endif

That way you can #include the file as many times as you want all over your code, in every code file even, and you will avoid multiple definition errors. To be fair I normally do it with the .h files and have something like:

// for absolutely insane safety/paranoia
#pragma once
// normally sufficient
#ifndef PERIPHERAL_1_H
#define PERIPHERAL_1_H
// my includes here
// my code here
#endif

I have never tried it on cpp files but wil llater tonight to see if there is any benefit one way or the other:)

Give me a shout if you need any more info:)

GMasucci
  • 2,834
  • 22
  • 42
  • Thank you for your answer. Maybe I did not correctly phrase my question. I do understand the techniques. I provided two links to prove I have studied it beofore asking the question.The actual question was: Why do I see lines #define PERIPHERAL_1_CPP #include "peripheral1.h" in peripheral1.cpp but not in the main or elsewhere? Or do I still miss something – Art Gertner Dec 12 '13 at 16:26
  • 1
    In simple words the intention of the code is to define the functions in "peripheral1.cpp" and use it across all other source files which includes "main". Hence it is declared in "main" also. – Uchia Itachi Dec 12 '13 at 16:45