Multiple includes of Arduino.h related to HardwareSerial

So this is probably a dumb question, but I've noticed that most libraries incliude Arduino.h. And Arduino.h includes HardwareSerial.h. And HardwareSerial.h instantiates the Serial object:

extern HardwareSerial Serial;

But since the different libraries are normally compiled into .o files, I think that means Arduino.h is actually included more than once. Which, since it has the above object would mean, there is more than one copy of Serial. (I'm actually assuming I'm wrong here... but that's my logic.)

Can anyone clarify what REALLY going on? (Since I assume I'm wrong.)

Thanks,
J

And HardwareSerial.h instantiates the Serial object:

No, it doesn't. It declares that an instance of the HardwareSerial class, called Serial, is declared external to the file.

I'm actually assuming I'm wrong here

Good, because you are. There is only one instance of HardwareSerial called Serial that gets created by HardwareSerial.cpp.

jeglenn:
So this is probably a dumb question, but I've noticed that most libraries incliude Arduino.h. And Arduino.h includes HardwareSerial.h. And HardwareSerial.h instantiates the Serial object:

extern HardwareSerial Serial;

But since the different libraries are normally compiled into .o files, I think that means Arduino.h is actually included more than once. Which, since it has the above object would mean, there is more than one copy of Serial. (I'm actually assuming I'm wrong here... but that's my logic.)

Can anyone clarify what REALLY going on? (Since I assume I'm wrong.)

Thanks,
J

It doesn't matter, because Arduino.h contains "guard statements" (which is a good if not essential thing to do with EVERY header file).

It works like this (fictional header file named "my_demo_header.h"):

// my demo header
#ifndef DEMO_HEADER_H
#define DEMO_HEADER_H

uint8_t my_var1;
uint16_t my_var2;
void my_function (uint8_t);
//... etc..

#endif

See what happens there? The FIRST time the header is included, the "#ifndef" (if not defined) rule is true, so everything up to the "#endif" is used (including the "#define"). This causes the header file to be loaded AND the define "DEMO_HEADER_H" to be created.

If some other sketch or library tries to load "my_demo_header.h" again, the "#ifndef" returns FALSE (since "DEMO_HEADER_H" now IS defined, so the rest is skipped (that is, the header is not erroneously loaded twice).

Now, Arduino.h has this guard in it, so "#include" it as many times as you want... only one will be used.

Another thing, in MOST cases (but not all), even if you #include a header, it's code doesn't take up any space UNLESS something in it is actually used.

You can experiment. In a sketch, compile it and see what size it is. Then, #include some random library that you don't use and compile the sketch again. You will see that the sketch compiles to the same size (MOST of the time... some libraries consume space even if they are not used... usually those that pre-instantiate themselves).

Hope this helps.

If some other sketch or library tries to load "my_demo_header.h" again, the "#ifndef" returns FALSE (since "DEMO_HEADER_H" now IS defined, so the rest is skipped (that is, the header is not erroneously loaded twice).

That is true for ONE compilation unit - one sketch OR one library. It is NOT true for all compilation units.

PaulS:
That is true for ONE compilation unit - one sketch OR one library. It is NOT true for all compilation units.

You want a cookie for that?

I said:

Another thing, in MOST cases (but not all),.....

You want a cookie for that?

Chocolate, with macadamia nuts, please.

PaulS:
Chocolate, with macadamia nuts, please.

My favorite is frosted oatmeal cookies. :slight_smile: