Why #ifndef LCD_H #define LCD_H

Go To Last Post
23 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I seen the following "code" in many internet examples and for the life of me cannot figure out what its purpose is.   I would have thought it had something to due with duplication but can't see how.

 

Can someone tell me the goal here?

 

Thanks

John

 

Code often found in  <program>.h files

#ifndef LCD_H
#define LCD_H

 

Last Edited: Wed. Jun 14, 2017 - 04:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The header file is ignored after the first inclusion as the define exists now, preventing duplication errors in the compiler (linker).

 

Jim

 

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

It's called a "header guard". You will probably get a better description if you google that but suppose you have:

#include "foo.h"
#include "lcd.h"

int main(void) {

}

but it turns out that "foo.h" itself includes:

#include "lcd.h"

then you end up reading the header multiple times.

 

The header guard arranges to

#define LCD_H

so that symbol is defined as soon as it's been seen once. Then when encountered later:

#ifndef LCD_H

ensures that all the rest of the file is ignored on the 2nd, 3rd, 18th, 231st, 1276834762nd time it is encountered.

 

PS forgot to point out that right down at the other end of the file there is a:

#endif

to match the #ifndef at the top and that's why the whole contents are skipped on the 2nd+ occasion

Last Edited: Wed. Jun 14, 2017 - 04:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohnRob wrote:
I seen the following "code" in many internet examples and for the life of me cannot figure out what its purpose is. I would have thought it had something to due with duplication but can't see how. Can someone tell me the goal here?

It is an oft-used mechanism to avoid an include file being processed more than once in the same context.

 

Say your code includes both a.h and b.h .  Both of those include c.h .  Without the mechanism, there would be a slew redefinition warnings for the second include of c.h .  There are other possible ramifications.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well I've always called this "header guard" but it seems Wikipedia choose "include guard":

 

https://en.wikipedia.org/wiki/In...

 

However this goes with my "header guard":

 

http://www.learncpp.com/cpp-tuto...

Last Edited: Wed. Jun 14, 2017 - 04:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was going to point out the alternative "#pragma once" but then I read this:

 

https://stackoverflow.com/questi...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Got it ....thanks.

 

It also helped when I found the #endif  hiding at the end of the file.

 

 

#endif //LCD_H

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I sometimes wonder if that is a bit of a failing of the pre-processor. You may often see:

#endif
#endif
#endif

at the end end of a file without much idea what these match to.

 

I suppose with modern, "source aware" editors that is not such a problem - they'll often highlight what such closure match with - but for a long time your only hope has possibly been a comment such as:

 //LCD_H

the author has seen fit to include to give an idea.

 

Then again in most .h file it's a pretty fair bet that at least the last #endif probably matches the header guard at the top.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using 

#pragma once

seems like a better way because it is simpler.  For instance you don't need the #endif at the end.

There may be a reason not to use it, but since GNU and Microsoft now allow it, I use it.  Well, their C++ compilers use it.  I don't know about their C compilers.  I suppose it's the preprocessors that use it.  I don't know if the C and C++ compilers use the same preprocessors.

 

I wonder why the preprocessor doesn't include a header file only once anyway.

 

I can't imagine why you would want to included a header twice, but if you do, I have the answer.

#pragma twice  smiley

 

Last Edited: Thu. Jun 15, 2017 - 01:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

But "#pragma once" is not part of the C standard (yet) so a lot of people won't rely on it as there's no guarantee all the compilers the code moves to will support it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll take a chance.  The pragma is much easier and simpler.  If something unexpected happens in the future, I'll write a pre-preprocessor.

 

The question still is, why doesn't the stupid preprocessor only use the header one time without me having to tell it to do that?

 

Speaking of stupid things, why must I not put spaces in a credit card number when entering it on the web?  The number has spaces on the credit card.  There's a reason for that. I can put spaces in a phone number but no no no spaces in a credit card number. 

 

Could it be there is only one idiot that writes web pages?  Must I wait for him to die before I can use spaces?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Though they were not headers, I have #included files more than once.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:

Though they were not headers, I have #included files more than once.

Nice try but that's a pretty lame excuse.  smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

> The question still is, why doesn't the stupid preprocessor only use the header one time without me having to tell it to do that?
Exactly because it is a stupid preprocessor doing simple text sustitutions. It is puposely designed so that when handling one #include it has no clue whatsoever if it has handled an identical #include earlier or will possibly handle one later.

Sometimes the KISS principle is a good thing..

Some people try to do advanced programming using the preprocessor. I csn imagine with horror what they might try to get away with if it was more advanced..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:

Though they were not headers, I have #included files more than once.


My understanding of the etymology of "header file" is that it is a file containing (function) headers, rather than the file on the whole being a header. I might be wrong. Let's discuss! :-)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

#ifndef aaa_h                 The preprocessor has to know if aaa has been previously defined. So it could also know if the aaa.h file was previously loaded.

#define aaa_h

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

steve17 wrote:
skeeve wrote:

Though they were not headers, I have #included files more than once.

Nice try but that's a pretty lame excuse.  smiley
Why call it an excuse?

In some cases, the #included files contained multiple invocations of the same macro.

Each #include was preceded by a different macro definition of that macro.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Nice try but that's a pretty lame excuse.

Why call it an excuse?

Indeed.  There are cases where you may >>want<< to include a header more than once, for example <util/setbaud.h>.  It would be inappropriate for the preprocessor to make those choices for me.

 

C is not a file manager, nor does the standard have much of anything to say about file management.

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Fri. Jun 16, 2017 - 03:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

steve17 wrote:
The question still is, why doesn't the stupid preprocessor only use the header one time without me having to tell it to do that?

It is not the preprocessor's place to guess the programmer's intentions.

 

The basic design philosophy of 'C' is, "you asked for it - you got it!".

 

If you tell it you want to shoot yourself in the foot, it will go ahead and do as you ask.

 

The preprocessor has to know if aaa has been previously defined. So it could also know if the aaa.h file was previously loaded.

No, it doesn't. 

 

It just knows that the things have been defined - not how or where they are defined.

 

 

Speaking of stupid things, why must I not put spaces in a credit card number when entering it on the web?  The number has spaces on the credit card.  There's a reason for that. I can put spaces in a phone number but no no no spaces in a credit card number. 

 

Could it be there is only one idiot that writes web pages?  Must I wait for him to die before I can use spaces?

That's a topic for a separate thread - in 'Off Topic'

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to note that these so-called "Include Guards" - aka "Header Guards" - have nothing to do with preventing "Multiple Definition" errors from the Linker ... 

 

#IncludeGuard #HeaderGuard

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Jun 16, 2017 - 04:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:

 

My understanding of the etymology of "header file" is that it is a file containing (function) headers, rather than the file on the whole being a header. I might be wrong. Let's discuss! :-)

Whatever I include I'm apt to call header files.  I always use the .h extension although I don't think that matters.

 

I think if I include any of my header files more than once I always get an error.  Most of mine are class descriptions and I get multiply defined errors, or something like that.  Of course they do contain function headers, and lots of other stuff.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also, <assert,h> is sometimes #included more than once.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
<assert,h> (sic)  is sometimes #included more than once.

And the whole point of Include (or Header) guards is that you can do that without worrying!

 

Here is the avr-libc source for assert.h: http://www.nongnu.org/avr-libc/u... (v2.0.0)

 

It doesn't have an Include/Header guard, but does begin with

#undef assert

So the last #include <assert.h> is the one which will actually be "seen" by the rest of the code ...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...