#pragma once vs ifndef....

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

I'm seeing the pragma more often and so was wondering what others do.

 

/* header include guard */
#ifndef FOO.H
#define FOO.H
....
#endif

VS

 

/* header include guard */
#pragma once
....

the second one is shorter, ie. quicker to type, but is it widely supported?

Just curious what others are doing.

TIA

Jim

 

This topic has a solution.

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

Last Edited: Mon. Sep 21, 2020 - 02:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does it make a difference if it is C or C++?  

I'm not a C++ guy so not sure if it is supported in C++.

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

I only use gcc/g++ so I've standardised on #pragma once. A quick google suggests it's a pretty standard 'non-standard' nowadays.

 

Include guards always seemed like a workaround in search of a 'proper' solution.

 

I wonder whether it's possible to structure a project's source files such that each header is only #included by one .c/.cpp file ? 

 

Or to use header files in such a way that multiple inclusions don't break the rules ? I see a lot of header files that contain what I would call 'code' rather than definitions.

 

From https://en.wikipedia.org/wiki/On...

The One Definition Rule (ODR) is an important rule of the C++ programming language that prescribes that objects and non-inline functions cannot have more than one definition in the entire program and template and types cannot have more than one definition by translation unit. It is defined in the ISO C++ Standard (ISO/IEC 14882) 2003, at section 3.2.

In short, the ODR states that:

  1. In any translation unit, a templatetypefunction, or object can have no more than one definition. Some of these can have any number of declarations. A definition provides an instance.
  2. In the entire program, an object or non-inline function cannot have more than one definition; if an object or function is used, it must have exactly one definition. You can declare an object or function that is never used, in which case you don't have to provide a definition. In no event can there be more than one definition.
  3. Some things, like types, templates, and extern inline functions, can be defined in more than one translation unit. For a given entity, each definition must have the same sequence of tokens. Non-extern objects and functions in different translation units are different entities, even if their names and types are the same.

 

Last Edited: Fri. Sep 18, 2020 - 07:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

obdevel wrote:
Include guards always seemed like a workaround in search of a 'proper' solution.

Have to agree with you on that!

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

I think pragma once started with microsoft but others have now adopted it but to be sure use ifndef guards

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


Why do I need #pragma once?  Why isn't once the default?   If someone wants more than once, he should use a pragma.

 

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

Why isn't once the default?

 because the pre-processor is supposed to be DUMB.  If you #include a file, it should plop in all the contents of that file.

 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

`#pragma once` was originally intended to provide functionality that is a bit different from what include guards do. The idea was that `#pragma once` would permit the preprocessor to cache the names of already-included files. If the same file is included again, the preprocessor would realize it just by looking at the name. It would not even try to locate the file in the file system, let alone re-parse it. This would improve the compiler's performance.

 

Originally `#pragma once` was headed for standardization. However, this theoretical idea crashed and burned in practice because in many (if not all) modern file systems it is often fairly difficult to say whether two given file names refer to the same file or to different files. That would generally require a full-blown request to the file system to locate the actual file (e.g. node). Also it is not entirely clear what should be considered "the same file" in link-enabled file systems. This, the intended specification of `#pragma once` proved to be too difficult to formulate and implement.

 

On top of that, a modern compiler can easily analyze the content of an ordinary header file with include guards on the first pass, and figure out whether this use of include guards is equivalent to `#pragma once`. I.e. the preprocessor can figure out that file does not require re-parsing every time it is included. That proved to be the final nail into the coffin of `#pragma once`.

 

Granted, `#pragma once` still offers some conveniences, like not having to invent a unique identifier, but that is typically not much of an issue.

 

Anyway, if you know that in your implementation `#pragma once` offers some preprocessing performance benefits you want to take advantage of (i.e. you know that your compiler/preprocessor is not smart enough to figure it out from include guards alone) then it might be a good idea to use `#pragma once` together with include guards. As for using just `#pragma once` by itself... meh.

Dessine-moi un mouton

Last Edited: Sat. Sep 19, 2020 - 02:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndreyT wrote:
then it might be a good idea to use `#pragma once` together with include guards

Well I never worried about how long the compile took, I guess my projects are not that big, but as for using both, it's too much typing, so I guess I'll continue to use the tried and true,
 

#ifndef

#define


#endif

 

method I have always used. 

Thanks for the feedback and excellent explanations!

Have a great day!

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

I use the pragma because it's simpler, easier and less error prone. 

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

ki0bk wrote:
it's too much typing
Not a good reason.

Too much reading would be a good reason.

Someone might need to read it later.

Too low an information density could make that annoying.

Avoiding repetition would be a good reason.

 

When I make a header file, I start it like this:

#ifndef FRED__H
#ifndef FRED__H
#ifndef FRED__H

With vi, a yyank and two puts avoids retyping the same symbol twice.

Of course, the second and third lines get edited.

Iluvatar is the better part of Valar.

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

All y'all have to do is what Mother Microsoft says:

We recommend the #pragma once directive for new code because it doesn't pollute the global namespace with a preprocessor symbol. It requires less typing, is less distracting, and can't cause symbol collisions, errors caused when different header files use the same preprocessor symbol as the guard value.Aug 29, 2019

 

once pragma | Microsoft Docs

docs.microsoft.com ›

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

Yeah.  What I said. 

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

We recommend the #pragma once directive for new code because it doesn't pollute the global namespace with a preprocessor symbol.

 Really?  There are ~16000 occurrences of "#define" in Atmel.SAMD21_DFP.1.3.395/samd21d/include/* and they're worrying about "polluting" the preprocessor name space with one-per-includefile symbols?

 

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

westfw wrote:
they're worrying about "polluting" the preprocessor name space with one-per-includefile symbols

No, more likely they are worried that two programmers out of the thousands they employ will...

theusch wrote:
errors caused when different header files use the same preprocessor symbol as the guard value

create the same symbol!  Far more likely to happen in a large project (you know, copy/paste errors and such).

Just one more way to reduce the number of reoccurring errors in builds.

 

Not likely a problem with our small projects most of us work on, or at least, what projects I work on any way!   smiley

 

Thanks for all the feedback!

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

ki0bk wrote:
create the same symbol!  Far more likely to happen in a large project (you know, copy/paste errors and such).

Just one more way to reduce the number of reoccurring errors in builds.

I usually derive the guard symbol from the file name.

Collisions are possible, but rather rare.

Iluvatar is the better part of Valar.

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

skeeve wrote:
I usually derive the guard symbol from the file name.

 

Collisions are possible, but rather rare.

True and same here, but I have seen when working with a group of programmers, that some use a coding template and copy/paste to begin with and forget to change the header guard to the file name.

So I have added that check to my "debug" list of things to check first when trouble shooting or doing a code review.

It happens, we have all done it, at least once.

 

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

ki0bk wrote:
skeeve wrote:
I usually derive the guard symbol from the file name.

 

Collisions are possible, but rather rare.

True and same here, but I have seen when working with a group of programmers, that some use a coding template and copy/paste to begin with and forget to change the header guard to the file name.

Don't put it in the template or make the template symbol 666symbol.
Quote:
So I have added that check to my "debug" list of things to check first when trouble shooting or doing a code review.
This strikes me as something that could be handled by the build system or the check in filter.
Quote:
It happens, we have all done it, at least once.
Not to me, but then my teammates have usually been working on a separate executable.

Iluvatar is the better part of Valar.

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

westfw wrote:

We recommend the #pragma once directive for new code because it doesn't pollute the global namespace with a preprocessor symbol.

 Really?  There are ~16000 occurrences of "#define" in Atmel.SAMD21_DFP.1.3.395/samd21d/include/* and they're worrying about "polluting" the preprocessor name space with one-per-includefile symbols?

'Tain't that silly.  How many of them end in __HH or __H ?

Mine do.

piano/.../keys.h and keyboard/.../keys.h might present a problem.

Iluvatar is the better part of Valar.

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

skeeve wrote:
might present a problem.
Though PIANO_KEYS_H and KEYB_KEYS_H would appear to offer the obvious solution.

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

Please... _PIANO_KEYS_H_ and _KB_KEYS_H_ :D

 

Neil (who has his own way of doing stuff)

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

Or PIANO_KEYS_H_

An identifier with leading underscore if you're very unlucky could clash with an identifier used for some purpose by the compiler.

I forget all the exact rules, but if you avoid leading underscore then it can't ever happen.

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

One underscore = C lib

Two underscore = Compiler

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

clawson wrote:
One underscore = C lib

Two underscore = Compiler

IIRC One underscore one capital also reserved for the compiler.

Iluvatar is the better part of Valar.

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

clawson wrote:
skeeve wrote:
might present a problem.
Though PIANO_KEYS_H and KEYB_KEYS_H would appear to offer the obvious solution.
Agreed.

Making it happen might be the sticking point.

If both are being developed by the same person or even the same team,

once the problem is noticed, said cure is obvious.

If they are part of externally developed distinct libraries,

changing the headers might be a problem.

Licensing and source code control issues come to mind.

There might be others.

#ifndef KEYSES__H
#define KEYSES__H 1

#include "piano/.../keys.h"
#undef KEYS__H
#include "keyboard/.../keys.h"

#endif // KEYSES__H

would seem to do the trick.

Iluvatar is the better part of Valar.

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

I use #pragma once because its easier and have found no reason to avoid it. Write the line once when creating a header file, done. Never have to touch that line again- change header name, change header location, still done. 

 

Out of curiosity I downloaded the latest Linux kernel to see how it would handle using pragma once. Out of some 18000+ header guards in use, about 600 are not unique. They also use the header guard names for more than header guards in many places, and they do some advanced things in the compile process with some of these headers so I excluded some headers by dir and some by certain keywords inside the header, but still ended up with about 13000 headers changed to pragma once.

 

I also left the header guard name define intact because I was only testing the pragma once, not their use of define names for other purposes. I also added an #if 1 so I wouldn't have to deal with the trailing #endif-

 

#ifndef _SOME_HEADER_H

#define _SOME_HEADER_H

...

#endif 

 

#pragma once

#define _SOME_HEADER_H

#if 1

...

#endif 

 

It compiled ok, and the compile time difference after the change was only a few seconds different (out of ~17 minutes). The fact that it worked simply means that pragma once worked as it should, which should not be a surprise since it should work the same for one file as it does thousands. It was a little bit of a pointless test, because it really didn't need to be run.

 

I don't know about all the scenarios in post #8 due to file systems, but I would think anyone using a header is not going to rely on include dir order to get the 'correct' header, so typically the header is specified by dir, so you still get a unique pragma once value in use-

 

#include <usb/config.h>

#include <timer/config.h>

 

if usb/config.h needs the timer config.h, its also going to specify <timer/config.h>, and the pragma once goes to work (when getting to the second one).

 

Trying to make something like Linux successfully compile for 'everyone' I'm sure is not an easy thing, but for the average avr or mcu user I have a hard time seeing where a problem will crop up by using pragma once. If there is a simple example that can show a problem, I would like to see it.

 

There are plenty of well known mcu projects that I would think would welcome the simplification (arduino, any OS you can find, etc.), but do not use it because they either don't know it exists or I guess don't feel comfortable doing anything different than was done before. I would think eliminating the need to create hundreds of unique defines would be a desirable thing.

 

It would really be nice if the compilers would flip this around- assume any include is wanted only once, and specify when that is not the case-

#pragma any

that way you switch the burden to the <1% of the time when you don't want it, instead of requiring the other >99% to do all the work.

 

My 2 cents.

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

yes

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

I'm not big on C (and smaller on C++) but after reading through this I'm on the "#pragma once" side.

 

Filename doesn't really matter - any half-decent compiler ought to be able to detect duplicated functions.  Cooking up unique (or "unique") identifiers is a pain and a problem, as other posters have observed in the Linux kernel.

 

Moreover, sometimes you might WANT the same code included several times.  Imagine a highly parallel system that wants sixteen copies of "a = b + c", running on sixteen cores...  I'm thinking of a similar construct in VHDL or Verilog when you need to instantiate, say, forty flip-flops...  #pragma Forty  or something...  smiley  S.

 

 

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

Thanks for all the feedback guys, I was squarely in the ifndef camp when I started, but am leaning more to the pragma camp now....   let the compiler handle this stuff......  

 

 

 

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

curtvm wrote:
Trying to make something like Linux successfully compile for 'everyone' I'm sure is not an easy thing, but for the average avr or mcu user I have a hard time seeing where a problem will crop up by using pragma once.
relative to AVR, pragma once in IAR EWAVR, not in CodeVisionAVR, not in MPLAB XC8 AVR.

IAR C/C++ Compiler User Guide for Microchip Technology’s AVR Microcontroller Family

[page 399]

Implementation-defined behavior for Standard C

...

 

[page 407]

...  the following directives are recognized and will have an indeterminate effect.

...

once

...

via User Guides: IAR Embedded Workbench for AVR

CodeVisionAVR Documentation

MPLAB XC8 C Compiler User’s Guide for AVR MCU via MPLAB® XC Compilers | Microchip Technology

 

"Dare to be naïve." - Buckminster Fuller

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

> not in MPLAB XC8 AVR

 

XC8 AVR is gcc based, so if they start ripping things like that out in their 'customized' version, then we know they have lost their minds. For XC8 PIC, I think you need to set it to C99 to get it to work (probably started to be possible after they changed compiler back end).