raghavan@umn-cs.CS.UMN.EDU (Vijay Raghavan) (01/28/89)
Is the Sun style of surrounding the text of standard "include" files with a #ifndef-#endif pair really okay? Specifically, does the standard condone/permit/require stdio.h (say) to have the following structure: #ifndef FILE ... #define FILE struct _iobuf ... #endif !__FILE If it does, programs like the following should not compile: main() { #include <stdio.h> FILE *xx; ... } proc1() { #include <stdio.h> FILE *yy; ... } Vijay Raghavan
gandalf@csli.STANFORD.EDU (Juergen Wagner) (01/28/89)
Vijay Raghavan (raghavan@umn-cs.cs.umn.edu) writes: > Is the Sun style of surrounding the text of standard "include" files I am not sure that's "Sun" style. It is just a way of preventing a header file from being included twice because you'll never know who else includes that particular file. >with a #ifndef-#endif pair really okay? Specifically, does the standard >condone/permit/require stdio.h (say) to have the following structure: Why should the standard require/forbid such files? There is a rationale for having them: Header files as found in /usr/include/... are supposed to contain global definitions and declarations, i.e. items which are typically included at the beginning of a module (not a function). Having things like stdio local to a function sounds a little strange, in particular because <stdio.h> on e.g. Suns says something like extern struct _iobuf {...} and a number of #defines, i.e. global declarations and definitions. Redefinition of these concepts isn't necessary/is treated as an error. > If it does, programs like the following should not compile: >... Why would one want to use such a program structure as opposed to having a single inclusion of <stdio.h>? I thought about it but couldn't come up with an answer. There certainly are other cases where multiple inclusion is meaningful. Yet, I would claim that in most of these cases, a single inclusion which defines an appropriate macro would be sufficient. I can be convinced of the opposite! -- Juergen Wagner gandalf@csli.stanford.edu wagner@arisia.xerox.com
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/28/89)
In article <10991@umn-cs.CS.UMN.EDU> raghavan@umn-cs.cs.umn.edu (Vijay Raghavan) writes:
- Is the Sun style of surrounding the text of standard "include" files
-with a #ifndef-#endif pair really okay? Specifically, does the standard
-condone/permit/require stdio.h (say) to have the following structure:
-#ifndef FILE
- ...
-#define FILE struct _iobuf
- ...
-#endif !__FILE
Well, more or less. There are several detailed points involved here.
- If it does, programs like the following should not compile:
-main() {
-#include <stdio.h>
-FILE *xx;
-...
-}
-proc1() {
-#include <stdio.h>
-FILE *yy;
-...
-}
The first point is that the standard headers may be included only
outside all function bodies (i.e. at file scope level).
The next point is that a #defined macro's scope extends to the end
of the translation unit, not just to the end of a block.
The third point is that FILE should be a typedef, not a #define.
The final point is that the standard headers may be included more
than once with no effect different from being included exactly once.
This is what the "#ifndef FILE" was attempting to accomplish.
raghavan@umn-cs.CS.UMN.EDU (Vijay Raghavan) (01/29/89)
In article <9526@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
<In article <10991@umn-cs.CS.UMN.EDU> raghavan@umn-cs.cs.umn.edu (I) wrote:
<>[...] does the standard
<>condone/permit/require stdio.h (say) to have the following structure:
<>#ifndef FILE
<> ...
<>#define FILE struct _iobuf
<> ...
<>#endif !__FILE
<
<Well, more or less. There are several detailed points involved here.
<
<> If it does, programs like the following should not compile:
<>main() {
<>#include <stdio.h>
<>FILE *xx;
<>...
<>}
<>proc1() {
<>#include <stdio.h>
<>FILE *yy;
<>...
<>}
<
<The first point is that the standard headers may be included only
<outside all function bodies (i.e. at file scope level).
May? Does this mean the same as "are required to"? (Excuse me, but
that simple English word "may" has always given me trouble. I think it
is because too many people use it as a synonym for "can").
My question was simple: Should a program like
the above give compilation errors? I don't necessarily adopt that style
of including the same header file in two different functions in the same
source file; I found it in a Path Pascal compiler I was porting to a Sun
environment. (Actually, the included file was "stat.h" but the point is
the same). Treat it as a question of academic interest only, if you like.
<
<The next point is that a #defined macro's scope extends to the end
<of the translation unit, not just to the end of a block.
I realize this of course. I think you missed the reason why the
program won't compile when the included file has the "#ifndef #endif"
pair surrounding it. It isn't because FILE is
not defined but because struct _iobuf is undefined in proc1().
<
<The third point is that FILE should be a typedef, not a #define.
I'll accept this if you say so (but note that a lot of implementations
seem to think otherwise). However, this makes no difference to the
example I gave. It still won't compile because the lexical scope of the typedef
will still be restricted to the main(){} block.
<
<The final point is that the standard headers may be included more
<than once with no effect different from being included exactly once.
<This is what the "#ifndef FILE" was attempting to accomplish.
I *know* what the "#ifndef FILE" was attempting to accomplish. All I am
saying is that the effect is not the same (as without the "#ifndef") when
the inclusions occur in different mutually non-nesting blocks of the same file.
Vijay Raghavan
gandalf@csli.STANFORD.EDU (Juergen Wagner) (01/30/89)
In article <10995@umn-cs.CS.UMN.EDU> raghavan@umn-cs.cs.umn.edu (Vijay Raghavan) writes: >... > My question was simple: Should a program like >the above give compilation errors? I don't necessarily adopt that style >of including the same header file in two different functions in the same >source file; I found it in a Path Pascal compiler I was porting to a Sun >environment. (Actually, the included file was "stat.h" but the point is >the same). Treat it as a question of academic interest only, if you like. Hmmm... you found that in a PASCAL compiler? Well, then the point is not the same because PASCAL allows you to restrict the scope of a function/variable to a function's/procedure's lexical scope. In C, there is no such concept except the idea of local variables (unless you split your file into multiple files, one top-level function per file, others static). With that in mind, I would still say that it doesn't seem to be meaningful to include standard header files more than once (remember: e.g. typedefs must not be included more than once). Note the word "standard". Somebody pointed me to the winner of the last Obfuscated C Contest. This program apparently used multiple header file inclusion deliberately to get some weird recursive effect. Coming back to the original point, I think, you can get dangerous effects from a number of sources: o If the header file defines a struct, your optimizer may decide to optimize the structs in different ways for the two functions. Exchanging data won't work then (e.g. one function writes the struct to a file, the other reads it. Parameter passing is out since the struct isn't defined globally). o #define macros will have to be #undef'ed before every definition to avoid nasty messages from cpp. You won't be able to distinguish accidental redefinitions from intended redefinitions otherwise. o If you look at standard header files like <dbm.h>, there are lines char pagbuf[PBLKSIZ]; char dirbuf[DBLKSIZ]; i.e. variable declarations. If you include the header file twice (and function-local), you will end up with two copies of the (supposedly) shared state variables. I guess, what you want is some kind of PASCAL-like scoping for C... -- Juergen Wagner gandalf@csli.stanford.edu wagner@arisia.xerox.com
diamond@csl.sony.JUNET (Norman Diamond) (01/30/89)
In article <10991@umn-cs.CS.UMN.EDU> raghavan@umn-cs.cs.umn.edu (Vijay Raghavan) writes: > main() { > #include <stdio.h> > FILE *xx; > ... > } > proc1() { > #include <stdio.h> > FILE *yy; > ... > } In article <9526@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: [First three points, good and helpful ones, omitted.] > The final point is that the standard headers may be included more > than once with no effect different from being included exactly once. True, but Mr. Raghavan unwittingly posed a problem. The effect must be as if the header were included exactly once, yes, -- but -- as if the header were included at which place? ! [I have been asked not to complain about inews requiring filler lines] -- Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net) The above opinions are my own. | Why are programmers criticized for If they're also your opinions, | re-inventing the wheel, when car you're infringing my copyright. | manufacturers are praised for it?
blarson@skat.usc.edu (Bob Larson) (01/30/89)
In article <7360@csli.STANFORD.EDU> gandalf@csli.stanford.edu (Juergen Wagner) writes: >o If you look at standard header files like <dbm.h>, there are lines > char pagbuf[PBLKSIZ]; > char dirbuf[DBLKSIZ]; > i.e. variable declarations. If you include the header file twice (and > function-local), you will end up with two copies of the (supposedly) > shared state variables. If you include this in two separatly compiled modules, it wouldn't work either. It looks like whoever wrote dbm.h forgot that C uses that def/ref linking model on some systems. (The declarations MUST be declared extern in all but one place.) Adding the extern keyword to these declarations might be adiquate for some systems, but the variables realy should be declared without the extern keyword in exactly one place. Since dbm.h wasn't written with portibility in mind, it isn't a good example. -- Bob Larson Arpa: Blarson@Ecla.Usc.Edu blarson@skat.usc.edu Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson Prime mailing list: info-prime-request%ais1@ecla.usc.edu oberon!ais1!info-prime-request
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/31/89)
In article <10995@umn-cs.CS.UMN.EDU> raghavan@umn-cs.cs.umn.edu (Vijay Raghavan) writes: -In article <9526@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: -<The first point is that the standard headers may be included only -<outside all function bodies (i.e. at file scope level). - May? Does this mean the same as "are required to"? No, because you're not required to include the header at all (unless, of course, you want to use something it declares or defines). You have official permission to include it ONLY at file scope level. ("may" as in "are allowed to") -I *know* what the "#ifndef FILE" was attempting to accomplish. All I am -saying is that the effect is not the same (as without the "#ifndef") when -the inclusions occur in different mutually non-nesting blocks of the same file. Thus the injunction against doing that.