Difference between pragma once inside and outside

2020-08-15 02:30发布

问题:

Is there any difference between placing the #pragma once inside the include guards as opposed to outside?

case 1:

#ifndef SOME_HEADER_H
#define SOME_HEADER_H
#pragma once

case 2:

#pragma once
#ifndef SOME_HEADER_H
#define SOME_HEADER_H

I'm just wondering out of curiosity if there's any special cases where I should prefer one or the other (case 1 or case 2) since I've decided to combine both (pragma and header guards) in my code.

EDIT:

I think you guys are misinterpreting my question... I am asking about the location of pragma once, not pragma once -vs- header guards.

回答1:

There's a subtle difference in that if SOME_HEADER_H is already defined before the header is included, then in the second case the preprocessor will process the #pragma once, and in the first case it won't.

You'll see a functional difference if you #undef SOME_HEADER_H and include the file again by the same TU:

#define SOME_HEADER_H
#include "some_header.h"
#undef SOME_HEADER_H
#include "some_header.h"

Now, in case 1 I have all the definitions from the header file. In case 2 I don't.

Even without the #undef, you could conceivably see a difference in preprocessing time due to the #pragma once being ignored in case 1. That's up to the implementation.

I can think of two plausible ways it could already be defined before the first inclusion of this header file:

  • (the obvious one) a completely separate file defines it, either deliberately or by accidental name clash,
  • a copy of this file has already defined it. Depending on implementation that might include the case where this file gets involved in the same TU under two different filenames, e.g. because of a symbolic link or filesystem merge. If your implementation supports #pragma once, and you examine its documentation very carefully, you may be able to find a definitive statement whether the optimization is applied by the path under which the file is included, or by comparison of something which identifies a file's storage, like inode number. If the latter, you may even be able to figure out whether there are still scams that could be pulled to trick the preprocessor, such as remote-mounting a local filesystem to conceal that it's "the same file really"...

Used in the expected way, though, there's no difference provided that the implementation treats #pragma once in the way that Microsoft defines it. As long as it's processed rather than skipped, it marks the containing file for the optimization, so it doesn't matter whether or not it would be processed on a second pass through the file -- the second pass won't happen.

And of course since the pragma is non-standard, at least in theory it could have a completely different meaning on different implementations, in which case it might matter when and how many times it is processed. In practice, you'd think nobody will do that.



回答2:

They're redundant.

#pragma once isn't supported by all compilers, while include guards are. Just use include guards. Compilers like gcc are smart enough to understand include guards and don't even open the file again.



回答3:

To answer your question:

Case 1:

The compiler will check if the preprocessor constant is set or not, if not define it and then check the #pragma ońce directive. This is most likely a hash lookup on the string "SOME_HEADER_H" to know if it's defined or not before doing another hash lookup on the current file name (probably the __ FILE __ constant set by the preprocessor). So if the file has never been read, we have two hash lookups and two hash saves, if the file has been read just a single hash lookup.

Case 2:

This is obviously the same thing as Case 1 but in opposite order. So the only thing we can compare is the length of the hash keys to use as lookup. Depending on the path to the current header file, i.e. the length of the path, the hash lookup for the #pragma once directive might be more expensive to calculate. If the file name is "C:\dude.h", it's shorter than "SOME_HEADER_H".

So I guess in summary. No. There's no special case where Case 1 would be more beneficial than Case 2 or vice versa. At least not yell Heureka over ;)

Cheers