#pragma once versus #ifndef

Feb 17, 2009 at 9:18am
I've heard that these are essentially the same:

1
2
3
4
5
6
//Automobile.h
#ifndef _AUTOMOBILE_H
#define _AUTOMOBILE_H
#else
//...
#endif 

vs
1
2
3
//Automobile.h
#pragma once
//... 


I've used the first way ("#ifndef") in the past... but "#pragma once" seems simpler and less lines to type and whatnot so I'm wondering if it's legit.

Thanks.
Feb 17, 2009 at 9:27am
closed account (z05DSL3A)
Pragmas are machine- or operating system-specific by definition, and are usually different for every compiler. So if you want your code to be portable use the first method.
Feb 18, 2009 at 3:18am
I've always used both. That way, if #pragma once is supported, it will include the file only once but if not, it is ignored and will used the #ifndef method. I wonder if that would be redundant...?
Feb 18, 2009 at 7:56am
The #ifndef version is wrong.
1
2
3
4
5
6
//Automobile.h
#ifndef _AUTOMOBILE_H
#define _AUTOMOBILE_H
//#else
//...
#endif  
Feb 18, 2009 at 1:14pm
@Zhuge it is redundant since all compilers support the include guard via #ifndef.
Feb 18, 2009 at 2:40pm
#pragma once can fail if the file system contains links to the same file that the compiler cannot follow.

For example, NTFS5 (Windows) supports hard links, but you can't detect that files are linked if you access the file system across an (SMB) network.
Last edited on Feb 19, 2009 at 8:53am
Feb 18, 2009 at 10:48pm
closed account (z05DSL3A)
Not only should you use a unique and predictable (internal) include guard but you should also consider using (external) include guards around each preprocessor include directive in header files.

The following is a small example, both a.h and b.h include base.h but preprocessor will have information to not even visit base.h a second time. It makes little difference on a small project, but a large difference on big ones.

1
2
3
4
5
6
7
8
9
10
11
// a.h
#ifndef INCLUDED_A
#define INCLUDED_A

#ifndef INCLUDED_BASE
#include "base.h"
#endif

//code

#endif 


1
2
3
4
5
6
7
8
9
10
11
// b.h
#ifndef INCLUDED_B
#define INCLUDED_B

#ifndef INCLUDED_BASE
#include "base.h"
#endif

//code

#endif 


1
2
3
4
5
6
7
// base.h
#ifndef INCLUDED_BASE
#define INCLUDED_BASE

//code

#endif 


Feb 18, 2009 at 11:24pm
That just sounds too redundant in my book. I guess the file would not need opened at compile time, but that can't gain much...am I missing something?
Feb 19, 2009 at 1:38am
I have to say, I don't see how that double guarding makes any difference whatsoever.
Feb 19, 2009 at 9:02am
Borland's Turbo Vision (a C++ Text GUI Framework) uses the double guarded style, and so does GNU's autoconfig, although that style uses HAS_xxx, where HAS_xxx is externally defined.
Feb 19, 2009 at 9:04am
closed account (z05DSL3A)
As I said, on small projects you will see not much of a difference.

When the preprocessor is doing it's business and finds an #include, it goes off loads the included file and reads the first line. It finds the guard definition and has a look to see if it is already defined. If it is it still has to process the file until it finds the corresponding #endif and then carry on processing the file to the end.

You may find that your compiler has include guard optimisation, but I have seen results that suggest this can be improved upon.

Feel free to search the net for "external include guards", I have also seen them referred to as "redundant include guards". You should see various peoples experiment results.
Feb 19, 2009 at 4:38pm
Oh! So it reduces compile time. I somehow thought you meant it protected against cyclic inclusion or something.
Last edited on Feb 19, 2009 at 4:38pm
Feb 19, 2009 at 4:41pm
closed account (z05DSL3A)
My bad, I thought that I had said it is to reduce compile time.
Feb 19, 2009 at 5:54pm
Still, not worth it, in my opinion. It clutters the code for hardly any benefit.
Topic archived. No new replies allowed.