Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

#pragma once

57 views
Skip to first unread message

r...@ai.mit.edu

unread,
Oct 30, 1989, 12:24:27 AM10/30/89
to
If you want to make sure a file won't be reincluded, you should use
`#pragma once' together with suitable conditionals that would prevent
multiple processing of the header file's contents. You can't rely on
`#pragma once'--it is just a time-saving hint.

If reinclusion would not cause any problem except for increased
compilation time, then you can use `#pragma once' by itself.

David Detlefs

unread,
Oct 30, 1989, 2:52:05 PM10/30/89
to
(This may be better placed in bug-gcc, but I don't normally read that.)

#pragma once has bothered me for a while. I recently corresponded
with Ron Guillemette (sp? sorry) on the issue, and the discussion
caused me to clarify the reasons for my uneasiness.

1) Reading Harbison and Steele's description of Draft Proposed ANSI C,
p. 254, we see that "... implementations should ignore [pragma]
information they do not understand." Thus, an ANSI C compiler may
validly include a .h file containing #pragma once multiple times.

2) rms recently posted that

>If you want to make sure a file won't be reincluded, you should use
>`#pragma once' together with suitable conditionals that would prevent
>multiple processing of the header file's contents. You can't rely on
>`#pragma once'--it is just a time-saving hint.

What happens if a file contains a #pragma once but does not contain
conditionals suitable to prevent it's contents from being processed
multiple times? It certainly seems to me that if the file is not
processed on inclusions after the first, then the (Draft Proposed)
ANSI standard has been violated. A C implementation that uses the
"#pragma" once in this way produces semantically different results
than one that ignores it; in effect, this interpretation makes it not
a "pragma," in the sense that this term is usually used (non-semantics
affecting.)

3) There is no way that I can see to make "#pragma once" safe; that
is, a pragma in the sense defined in the ANSI C proposal. The only
way to do so is to have cpp do enough analysis to determine whether
the #pragma once file contains "suitable conditionals" (to use rms's
term) to prevent subsequent reinclusion. Even then, an including file
might #undef the variable whose definedness prevents processing. If
this is not recognized, semantics are not preserved. The best idea I
have ever heard along these lines was recently reiterated by John
Nagle on comp.lang.c++ (I don't know if it's original with him):

have cpp recognize files of the common form

<foo.h>:
<comments/whitespace>
#ifndef <foo_defined>
<body>
#endif
<comments/whitespace>

maintain a table associating filenames <foo.h> with variables
<foo_defined>.

whenever we encounter

#include "<foo.h>"

check to see if <foo.h> is in the table, and if so, if the
corresponding <foo_defined> is currently defined. If so, we may
safely pass over the #include.

Note that this gets all the performance savings of #pragma once,
while maintaining ANSI semantics. If you read rms's post again,
you'll note that you are supposed to use *both* #pragma once and the
#ifndef style. This proposal obviates the need for the #pragma once.

This is not my idea, but I really think it's a good one. Hope I've
convinced somebody.

--
Dave Detlefs Any correlation between my employer's opinion
Carnegie-Mellon CS and my own is statistical rather than causal,
d...@cs.cmu.edu except in those cases where I have helped to
form my employer's opinion. (Null disclaimer.)

Glen Ditchfield

unread,
Oct 30, 1989, 4:55:55 PM10/30/89
to
In article <DLD.89Oc...@F.GP.CS.CMU.EDU> d...@F.GP.CS.CMU.EDU (David Detlefs) writes:

> ... The best idea I have ever heard along these lines was recently


>reiterated by John Nagle on comp.lang.c++ (I don't know if it's original
>with him):
>
>have cpp recognize files of the common form
>
><foo.h>:
><comments/whitespace>
>#ifndef <foo_defined>
><body>
>#endif
><comments/whitespace>
>

> ... Note that this gets all the performance savings of #pragma once,


>while maintaining ANSI semantics. If you read rms's post again,
>you'll note that you are supposed to use *both* #pragma once and the
>#ifndef style. This proposal obviates the need for the #pragma once.

Some other, weaker points:
- For better or worse, the "Nagle" system would allow programmers to force
reinclusion by undefining <foo_defined>. I don't how to override
"#pragma once"; I'll bet there is a way, and I'll bet that it would vary
among compilers that implement "#pragma once".
- I often pass my C++ code through g++ and through AT&T's system. The
obsolescent cpp used here with cfront complains that it doesn't know what
to do with "#pragma", so I've gotten out of the habit of using "#pragma
once". (I agree that the proper thing to do is to change preprocessors,
but ...)
- Other systems have already taken other approaches. If I remember
correctly, one C compiler had "#pragma idempotent", while Objective C's
preprocessor tackled the problem from the other end with "#import".
"#ifndef/#endif" works for all of them. I think it's easier to provide
an optimization for this idiom than to get all implementors to agree to a
single extension.

David C Lawrence

unread,
Oct 31, 1989, 2:17:59 AM10/31/89
to
Someone made a suggestion a little while ago for expanding the once
pragma into a something more active in what it did -- a system of
requires and provides. For example, #pragma require stdio.h and
#pragma provide news.h. Is there anything very wrong with this that
would make it undesirable in a production environment?
--
(setq mail '("ta...@pawl.rpi.edu" "ta...@ai.mit.edu" "ta...@rpitsmts.bitnet"))

Ron Guilmette

unread,
Nov 1, 1989, 12:43:52 PM11/1/89
to
In article <30...@watmath.waterloo.edu> gjditc...@watmsg.waterloo.edu (Glen Ditchfield) writes:
>- I often pass my C++ code through g++ and through AT&T's system. The
> obsolescent cpp used here with cfront complains that it doesn't know what
> to do with "#pragma", so I've gotten out of the habit of using "#pragma
> once". (I agree that the proper thing to do is to change preprocessors,
> but ...)


But what? Are you fanatically ANTI-ANSI?

// rfg

Doug Ingraham

unread,
Nov 3, 1989, 1:34:17 AM11/3/89
to

I have been working on and off on a portable ANSI library for the last
couple of years (mostly off). I have ctype.h and string.h support working
and am writing the documentation and a validation suite. I recently went
through and added all the #ifdefs for the prototypes in the sources and while
I was at it I added #pragma once to the include files. The #pragma once
is a very good idea, unfortunatly it does cause non-ansi compilers to choke
a little. To get rid of the errors I #ifdef out the #pragma once lines as
follows for the case of <string.h>:

#ifdef __GNUC__
#pragma once
#endif
#ifndef __STRING_H
#define __STRING_H

< The required string.h information here >

#endif /* __STRING_H */

This looks like it should work everywhere and will make use of a most
valuable FEATURE of GNUC. I of course didn't put any of the above
code in the assert.h header because it is desirable to be able to change
NDEBUG and re-include <assert.h>.

In case anyone is interested, I did include support for locale's other
than the C locale. At this time only the hooks are there since I don't
know enough about the specific implementation details of foreign locales.
This was the most difficult area of the ANSI Draft to interpret.

If the person(s) working on the gcc library are interested in any of this
let me know.

--
Doug Ingraham (SysAdmin)
Lofty Pursuits (Public Access for Rapid City SD USA)
uunet!loft386!dpi

Marshall Cline

unread,
Nov 3, 1989, 4:09:45 PM11/3/89
to
In article <DLD.89Oc...@F.GP.CS.CMU.EDU> d...@F.GP.CS.CMU.EDU (David Detlefs) writes:
>have cpp recognize files of the common form
><foo.h>:
><comments/whitespace>
>#ifndef <foo_defined>
><body>
>#endif
><comments/whitespace>
>maintain a table associating filenames <foo.h> with variables
><foo_defined>.
>whenever we encounter
>#include "<foo.h>"
>check to see if <foo.h> is in the table, and if so, if the
>corresponding <foo_defined> is currently defined. If so, we may
>safely pass over the #include.

This has now been suggested by several, however there's a potential problem.
The original posting indicated all one need do is verify the file begins
with "#ifndef _FOO_H_" and that it ends with "#endif". *BUT*...

#ifndef _FOO_H_
#define _FOO_H_
<stuff expanded the first time this file is included>
#else
<stuff expanded the other times this file is included>
#endif

The point is: whoever is going to implement this for FSF, *please* be
*careful*! You have to verify (as a minimum?) that there are no #else's
which match the original #ifndef.

Marshall
--
_______________________________________________________________________________
Marshall P. Cline/ 225 Clarkson Hall/ ECE Dept/ Clarkson Univ/ Potsdam NY 13676
Internet: cl...@sun.soe.clarkson.edu -or- bh...@clutx.clarkson.edu
BitNet: bh0w@clutx Usenet: uunet!sun.soe.clarkson.edu!cline
Voice: 315-268-3868 (office)

Andrew Klossner

unread,
Nov 3, 1989, 1:03:00 PM11/3/89
to
> #ifdef __GNUC__
> #pragma once
> #endif

> This looks like it should work everywhere ...

No, this will not work everywhere. A preprocessor must read #word
directives even in non-compiled code, to find the end of that code.
Some preprocessors will lose their cookies over the pragma.

For example, if I run this fragment through the compiler on my
Tektronix 4316, it says:

"x.c", line 2: cpp : undefined control

-=- Andrew Klossner (uunet!tektronix!frip.WV.TEK!andrew) [UUCP]
(andrew%frip.wv...@relay.cs.net) [ARPA]

David Keppel

unread,
Nov 4, 1989, 2:11:09 PM11/4/89
to
In article <52...@orca.WV.TEK.COM> and...@frip.wv.tek.com writes:
:> #ifdef __GNUC__
:> #pragma once
:> #endif
:
:For example, if I run this fragment through the compiler on my

:Tektronix 4316, it says:
:
: "x.c", line 2: cpp : undefined control

As a practical matter, most compilers will do the right thing if you
say:

#ifdef __GNUC__
#pragma once
#endif

;-D on ( Token pasting with "Krazy" Glew ) Pardo
--
pa...@cs.washington.edu
{rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo

Doug Ingraham

unread,
Nov 5, 1989, 4:48:15 PM11/5/89
to

Thanks for pointing this out. I also received a note from
Rich Saltz but couldn't thank him via mail as it bounced.

I tried this on several compilers with success on all at my
disposal. I now have 2 options:

1) Ignore portability and concentrate on a GNU/ANSI only version.

2) Drop the usage of #pragma once and try to remain portable.

Actually, I favor ignoring portability to non ANSI-C because
I like using prototypes. I think the #ifdef constructs around
function declarations are ugly and obfuscate the meaning of the
code. Any constructive comments would be welcome.

Mark H. Colburn

unread,
Nov 8, 1989, 8:46:26 AM11/8/89
to
In article <5...@loft386.UUCP> d...@loft386.UUCP (Doug Ingraham) writes:
>#ifdef __GNUC__
>#pragma once
>#endif
>#ifndef __STRING_H
>#define __STRING_H
>
>< The required string.h information here >
>
>#endif /* __STRING_H */

Ok, I'll finally admit it, I am a little confused as to why there is such a
construct as the #pragma once.

If you want to avoid including the file twice, why not use the "standard"
method of enclosing the entire thing in "#ifdefs" as shown above:

#ifndef __MYHEADER_H
#define __MYHEADER_H

<header stuff>

#endif /* __MYHEADER_H */

This works on any machine with a preprocessor, is portable across any
compiler, does not use a #pragma, and is in widespread use today. Also,
from the discussion which has ensued here about #pragma once, I assume that
it does not always work correctly.

Can someone enlighten me here?

--
Mark H. Colburn ma...@Minnetech.MN.ORG
Open Systems Architects, Inc.

David Keppel

unread,
Nov 9, 1989, 12:37:30 PM11/9/89
to
ma...@jhereg.UUCP (Mark H. Colburn) writes:
>[Why `#pragma once'? What's wrong with
> #ifndef TOKEN
> #define TOKEN
> ...
> #endif TOKEN
>]

It's slow, particularly if you have nested includes. The problem is
that with `#ifndef TOKEN ... #endif' the entire file must be scanned
each place that the #include directive appears, even if the #include
is redundent. With `#pragma once', the compiler can avoid redundent
rescans.

An portable alternative convention avoids the overhead of rescanning
but requires more programmer work and allows more typos:

#ifndef TOKEN
# include TOKEN
#endif

I ususually combine the latter with lines in the .h that look like

#ifdef TOKEN
{ TOKEN multiply defined! }
#else
#define TOKEN
...
#endif

Alternatively, you can just do `#ifndef TOKEN ... #endif' and let
the compile go slow if you (somebody) does some repeated includes.

To summarize: `#pragma once' provides a facility that is available by
other mechanisms. The advantage of `#pragma once' is that information
about the use of the .h is not spread through both the .h and the .c.
Using `#pragma once' does not compromise portability if the `#prgama
once' is ifdeffed.

#ifdef __STDC__
#pragma once
#endif

Note that the octothorpe ('#') should be indented to keep older
compilers from gagging.

;-D on ( #pragma once upon a time ) Pardo
--
pa...@cs.washington.edu
{rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo

Colin Plumb

unread,
Nov 9, 1989, 2:44:43 PM11/9/89
to
In article <3...@jhereg.Minnetech.MN.ORG> ma...@jhereg.UUCP (Mark H. Colburn) writes:
> Ok, I'll finally admit it, I am a little confused as to why there is such a
> construct as the #pragma once.
>
> If you want to avoid including the file twice, why not use the "standard"
> method of enclosing the entire thing in "#ifdefs" as shown above:
>
> This works on any machine with a preprocessor, is portable across any
> compiler, does not use a #pragma, and is in widespread use today. Also,
> from the discussion which has ensued here about #pragma once, I assume that
> it does not always work correctly.

No, it works fine, it's just inefficient. The preprocessor has to open the
file, parse it, including such pathological situations as

printf("\
#endif /* \
*/");

and all to include a few carriage returns in the source file. #pragma once
lets the prorpocessor just skip over future #includes of the same file, not
even opening the file for examination. With ANSI type-checking, header files
are bigger than ever, and reducing time spent parsing them becomes more
important.
--
-Colin

0 new messages