rms@AI.MIT.EDU (10/30/89)
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.
dld@F.GP.CS.CMU.EDU (David Detlefs) (10/31/89)
(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, dld@cs.cmu.edu except in those cases where I have helped to form my employer's opinion. (Null disclaimer.)
gjditchfield@watmsg.waterloo.edu (Glen Ditchfield) (10/31/89)
In article <DLD.89Oct30145205@F.GP.CS.CMU.EDU> dld@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.
mark@jhereg.Minnetech.MN.ORG (Mark H. Colburn) (11/08/89)
In article <522@loft386.UUCP> dpi@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 mark@Minnetech.MN.ORG Open Systems Architects, Inc.
pardo@cs.washington.edu (David Keppel) (11/10/89)
mark@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 -- pardo@cs.washington.edu {rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo
ccplumb@rose.waterloo.edu (Colin Plumb) (11/10/89)
In article <305@jhereg.Minnetech.MN.ORG> mark@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