#once
C Document number: N2742
Date: 2021-10-17
Author: Miguel Ojeda <ojeda@ojeda.dev>
Project: ISO/IEC JTC1/SC22/WG14: Programming Language C
This proposal adds a standard version of the #pragma once
feature implemented in major compilers.
The #pragma once
feature is provided by compilers as a more ergonomic include guard, i.e. instead of writing a header like:
/*
* Some header.
*/
#ifndef SOME_HEADER_H
#define SOME_HEADER_H
// File contents
#endif // SOME_HEADER_H
Users may write it like:
/*
* Some header.
*/
#pragma once
// File contents
The feature is supported in all major compilers:
However, the semantics of “having seen a file” can be unclear (e.g. is it based on the path? On the inode? On the contents?) and unreliable (e.g. filesystem aliasing), thus some projects like the Linux kernel prefer to avoid using #pragma once
, though they may use such a feature if it allows to provide an identifier [1].
This proposal adds a new preprocessing directive, #once
, as a standard and shorter version of #pragma once
, in two variants.
The first variant has implementation-defined semantics and the intention is that translators that already provide #pragma once
give it the same semantics (and document them):
/*
* Some header.
*/
#once
// File contents
The benefits of this variant with respect to #pragma once
is that it is standard and shorter.
The second variant, which takes an identifier, is a replacement for an explicit include guard for projects that do not wish to rely on the interpretation of “having seen a file” that their compilers may do:
/*
* Some header.
*/
#once SOME_HEADER_H
// File contents
The benefits of this variant with respect to an explicit include guard is that it is standard, shorter and avoids duplicating the identifier (twice if the project uses the fairly common convention of writing it also in the #endif
directive as a comment).
Both variants are required to come before any other preprocessor directive, but may come after text lines (typically, comments such as a top-level description of the header or a SPDX [2] line). Only a single #once
directive is allowed per source file (though more may appear in the preprocessing translation unit).
The proposed wording is with respect to the N2596 C23 Working Draft.
In “4. Conformance”, after paragraph 4 add a new one:
The implementation shall not successfully translate a source file containing more than one
#once
preprocessing directive or containing one if it is not the first preprocessing directive in the source file.
In “6.10 Preprocessing directives”, modify paragraph 1 to add the #once
directive after #error
and before #pragma
:
…
control-line:
…
#
error
pp-tokensopt new-line
#
once
new-line
#
once
identifier new-line
#
pragma
pp-tokensopt new-line…
After “6.10.5 Error directive”, add a new section:
6.10.6 Once directive
Semantics
A preprocessing directive of the form
#
once
new-linecauses the implementation to behave in an implementation-defined manner.
A preprocessing directive of the form
#
once
identifier new-linecauses the implementation to behave as if the source file was prefixed with
#ifndef
identifier
#define
identifierand suffixed with
#endif
If more than one
#once
directive appears in the source file, or if a preprocessing directive appears before it, then this causes the implementation to produce a diagnostic message.