jeff@oakhill.UUCP (Jeff Enderwick) (10/16/90)
This has probably come up before ... Is it legal for a compilation system to require prototypes when stdarg functions are used ? It valid for the compiler to require you to include the prototype: int printf ( const char*, ... ); before making the call: printf ( "hello %d worlds\n", 5 ); ? If not, where does the ANSI spec say so ? Jeff Enderwick DSP Compiler Development Motorola, Inc. (512) 891-3388 cs.utexas.edu!oakhill!otis!jeff
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/17/90)
In article <4026@otis.oakhill.UUCP> jeff@oakhill.UUCP (Jeff Enderwick) writes: >Is it legal for a compilation system to require prototypes when stdarg >functions are used ? It valid for the compiler to require you to include >the prototype: > int printf ( const char*, ... ); >before making the call: > printf ( "hello %d worlds\n", 5 ); Yes, you definitely must have a prototype in scope before calling a variable-argument function in a strictly conforming program. For printf(), you should #include <stdio.h> instead of declaring it yourself. You might get better results that way in some implementations.
volpe@underdog.crd.ge.com (Christopher R Volpe) (10/17/90)
In article <14164@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes: |>In article <4026@otis.oakhill.UUCP> jeff@oakhill.UUCP (Jeff Enderwick) writes: |>>Is it legal for a compilation system to require prototypes when stdarg |>>functions are used ? It valid for the compiler to require you to include |>>the prototype: |>> int printf ( const char*, ... ); |>>before making the call: |>> printf ( "hello %d worlds\n", 5 ); |> |>Yes, you definitely must have a prototype in scope before calling a |>variable-argument function in a strictly conforming program. Two questions: 1) Can you point me to a reference in the standard that says that old-style declarations are insufficient for a variable argument function in a strictly conforming program? Or are old style declarations insufficient for ANY kind of function in a strictly conforming program? 2) Are you sure you answered the question he asked? Jeff asked if it is valid for the compiler to REQUIRE YOU TO include the prototype. To me, "require you to" means "refuse to generate code unless you...". That's a different issue. Unless a program violates a syntax rule or a semantic constraint, the compiler can at most issue a warning but must still generate code. I believe (please correct me if I'm wrong) that a program can fail to be strictly conforming (and even fail to be conforming) without violating any semantic constraints. Is this correct? ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
pds@lemming.webo.dg.com (Paul D. Smith) (10/17/90)
[] Is it legal for a compilation system to require prototypes when stdarg [] functions are used ? The thing you need to remember is that, in the definition of the stdarg package, each function *must* have at least the first argument defined; i.e., you cannot declare a function as: int my_func( ... ); You must have at least one argument (see K&R II, Sec B7, p 254). So, if you are going to add the "..." construct you must declare a prototype for the first argument. I see no reason you could just not prototype anything, however: int printf(); This should cause no problems. -- paul ----- ------------------------------------------------------------------ | Paul D. Smith | pds@lemming.webo.dg.com | | Data General Corp. | | | Network Services Development | "Pretty Damn S..." | | Open Network Applications Department | | ------------------------------------------------------------------
Christopher-Vance@adfa.oz.au (10/18/90)
gwyn@smoke.BRL.MIL (Doug Gwyn) writes: | Yes, you definitely must have a prototype in scope before calling a | variable-argument function in a strictly conforming program. Which means that gcc -ansi on a Pyramid cannot compile such a thing. I am informed that the only way to make printf work is to *omit* the prototype.
karl@haddock.ima.isc.com (Karl Heuer) (10/18/90)
In article <1964@ccadfa.adfa.oz.au> Christopher-Vance@adfa.oz.au writes: >gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >| Yes, you definitely must have a prototype in scope [for printf()] > >Which means that gcc -ansi on a Pyramid cannot compile such a thing. I am >informed that the only way to make printf work is to *omit* the prototype. Presumably this is caused by having to link with the native implementation of printf(), and hence will be fixed when the FSF releases the GNU library. Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
diamond@tkou02.enet.dec.com (diamond@tkovoa) (10/18/90)
In article <12826@crdgw1.crd.ge.com> volpe@underdog.crd.ge.com (Christopher R Volpe) writes: > 1) Can you point me to a reference in the standard that says that > old-style declarations are insufficient for a variable argument > function in a strictly conforming program? Section 3.5.4.3 plus section 3.7.1 together do this. Section 3.5.4.3, semantics, sixth paragraph: "If one type has a parameter list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator..." Thus, if there is a non-defining declaration of printf without a prototype, then all definitions and declarations of printf that do have prototypes must not have an ellipsis. Section 3.7.1, semantics, second paragraph: "If a function that accepts a variable number of arguments is defined without a parameter list that ends with the ellipsis notation, the behavior is undefined." Thus, if printf's implementation is defined in ANSI C, it must be defined with a prototype that ends with an ellipsis. If your <stdio.h> does not declare printf, and your library provides a definition of printf that was not coded in ANSI C, then it seems that a loophole allows you to make your own extern declaration of printf without a proper prototype. I would not suggest depending on this. I didn't check if there's another loophole that might permit printf to be called (with defined results) without any declaration at all, but it doesn't seem likely. You know how to do that check. > 2) Are you sure you answered the question he asked? Jeff asked if > it is valid for the compiler to REQUIRE YOU TO include the > prototype. To me, "require you to" means "refuse to generate > code unless you...". That's a different issue. Unless a program > violates a syntax rule or a semantic constraint, the compiler > can at most issue a warning but must still generate code. I > believe (please correct me if I'm wrong) that a program can > fail to be strictly conforming (and even fail to be conforming) > without violating any semantic constraints. Is this correct? The standard does not really define "REQUIRE YOU TO", although the word "shall" and the word "undefined" are meta-defined in a meta-standard. I would say that a compiler can require you to include the prototype. -- Norman Diamond, Nihon DEC diamond@tkov50.enet.dec.com (tkou02 is scheduled for demolition) We steer like a sports car: I use opinions; the company uses the rack.
lewine@dg-rtp.dg.com (Donald Lewine) (10/18/90)
In article <12826@crdgw1.crd.ge.com>, volpe@underdog.crd.ge.com (Christopher R Volpe) writes: |> |> Two questions: |> 1) Can you point me to a reference in the standard that says that |> old-style declarations are insufficient for a variable argument |> function in a strictly conforming program? Or are old style declarations |> insufficient for ANY kind of function in a strictly conforming |> program? OK. See section 3.7.1: "If a function that accepts a variable number of arguments is defined without a parameter type list that ends with the ellipsis notation, the behavior is undefined." This allows the compiler to generate a different calling sequence for functions with a fixed number of argument and a variable number of arguments. See section 4.8 in the rationale. |> |> 2) Are you sure you answered the question he asked? Jeff asked if |> it is valid for the compiler to REQUIRE YOU TO include the |> prototype. To me, "require you to" means "refuse to generate |> code unless you...". That's a different issue. Unless a program |> violates a syntax rule or a semantic constraint, the compiler |> can at most issue a warning but must still generate code. I |> believe (please correct me if I'm wrong) that a program can |> fail to be strictly conforming (and even fail to be conforming) |> without violating any semantic constraints. Is this correct? Well, if the implementation uses one calling sequence (say, with arguments in registers) for functions with a known number of arguments and uses a different calling sequence (say, with arguments on the stack) for functions with a variable number of arguments, the generated code will not call the library correctly unless the function is correctly declared. I will admit that you may not get an error message, but the code will not work! Note also that the definition of ANSI C was done to allow a compiler to generate calls with arguments in registers and several new RISC compilers take advantage of that. -------------------------------------------------------------------- Donald A. Lewine (508) 870-9008 Voice Data General Corporation (508) 366-0750 FAX 4400 Computer Drive. MS D112A Westboro, MA 01580 U.S.A. uucp: uunet!dg!lewine Internet: lewine@cheshirecat.webo.dg.com
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/18/90)
In article <1964@ccadfa.adfa.oz.au> Christopher-Vance@adfa.oz.au writes: >gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >| Yes, you definitely must have a prototype in scope before calling a >| variable-argument function in a strictly conforming program. >Which means that gcc -ansi on a Pyramid cannot compile such a thing. I am >informed that the only way to make printf work is to *omit* the prototype. As I said before, you should rely on <stdio.h> to properly declare printf(). If <stdio.h> is not included at all, then the C standard guarantees that you could declare printf() directly in your program, providing that you use the prototype specified in the standard. "extern int printf();" on the other hand has undefined behavior.
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/18/90)
In article <PDS.90Oct17103016@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes: >I see no reason you could just not prototype anything, however: > int printf(); >This should cause no problems. No, that's wrong. As point of contact when the <stdarg.h> macros were being worked out, I received many examples of implementations where such a declaration would result in the wrong code being generated for linkage to a variable-argument function. This is reflected in the requirements for strict program conformance in the C standard; the above declaration is not strictly conforming, and it does matter.
markhall@pyrps5.pyramid.com (Mark Hall) (10/19/90)
In article <18561@haddock.ima.isc.com> karl@ima.isc.com (Karl Heuer) writes: >In article <1964@ccadfa.adfa.oz.au> Christopher-Vance@adfa.oz.au writes: >>gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >>| Yes, you definitely must have a prototype in scope [for printf()] >> >>Which means that gcc -ansi on a Pyramid cannot compile such a thing. I am >>informed that the only way to make printf work is to *omit* the prototype. There are two issues to cover here. First, Doug said (quoting loosely) "you must have a prototype in scope [for the *program* to be strictly conforming]". He didn't say that an ANSI compiler had to flag the non-conformance. Second, let me point out that on some architectures, the calling sequence changes if you are calling a stdarg function (put args on the stack instead of in registers, say). If you don't have an ellipsis prototype visible at the call site, the compiler will not know to emit the correct calling sequence, and hence the program will die mysteriously or give obscure results at runtime. Does the ANSI compiler which compiled this program have to tell you ahead of time that you forgot the prototype? No. The adjective "conforming" applies to programs, not compilers. So does "gcc -ansi" really reject a program which calls a stdarg function without a prototype? Does it manufacture a link-time check? Otherwise, how can it tell "printf" is a stdarg function? > >Presumably this is caused by having to link with the native implementation of >printf(), and hence will be fixed when the FSF releases the GNU library. > I'm not sure what the problem is with the the Pyramid printf function which is incompatible with gcc when you have an ellipsis prototype for printf. Does gcc put ellipsis arguments on the stack or something? If so, why? -Mark Hall (smart mailer): markhall@pyrps5.pyramid.com (uucp paths): {ames|decwrl|sun|seismo}!pyramid!markhall
rfg@NCD.COM (Ron Guilmette) (10/19/90)
In article <14164@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >In article <4026@otis.oakhill.UUCP> jeff@oakhill.UUCP (Jeff Enderwick) writes: >>Is it legal for a compilation system to require prototypes when stdarg >>functions are used ? It valid for the compiler to require you to include >>the prototype: >> int printf ( const char*, ... ); >>before making the call: >> printf ( "hello %d worlds\n", 5 ); > >Yes, you definitely must have a prototype in scope before calling a >variable-argument function in a strictly conforming program. > >For printf(), you should #include <stdio.h> instead of declaring it >yourself. You might get better results that way in some implementations. Along the same lines, I also have a related question. Now please excuse my almost total ignorance regarding the x3j11 requirements regarding the contents of include files, but I don't immediately see where (in 4.9.1) it says (explicitly) what function are required to be declared within <stdio.h>. Are all of the function listed in 4.9.4 thru 4.9.10 required to have declarations within <stdio.h>? If so, are they required to have prototyped declarations? Non-prototyped? Either? Part of the reason that I ask is that I was doing some work recently on a machine for which the va_list type is a structure, and I encountered an odd problem. I was porting some code to this machine, and I got an error on a hunk of code like: #include <stdio.h> ... ... va_list args; ... vfprintf (file, fmt, args); /* <= error here */ as it turned out, the creators of the <stdio.h> file in question had cheated and put a declaration like the following in it: int vfprintf (FILE *, const char *, void *); Obviously, that last formal parameter type is not correct! That's why I got an error at the call. I tried changing the last formal type to (a more correct) `va_list', but when I did that this changed the <stdio.h> file into something that could *not* be included ALL BY ITSELF into *any* given file. Rather, it now always had to be preceeded by a #include <stdarg.h>. So what it the `correct' thing to have in the <stdio.h> file regarding the vfprintf function (and friends)? -- // Ron Guilmette - C++ Entomologist // Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
darcy@druid.uucp (D'Arcy J.M. Cain) (10/19/90)
In article <1964@ccadfa.adfa.oz.au> Christopher-Vance@adfa.oz.au writes: >gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >| Yes, you definitely must have a prototype in scope before calling a >| variable-argument function in a strictly conforming program. > >Which means that gcc -ansi on a Pyramid cannot compile such a thing. I am >informed that the only way to make printf work is to *omit* the prototype. Is gcc on the Pyramid broken that badly? On my SysV 386 system: $ cat ptest.c extern int printf(const char *format, ...); int main(void) { printf("%d %s\n", 5, "Hello world"); return(0); } $ gcc -Wall -ansi ptest.c -o ptest $ ptest 5 Hello world $ -- D'Arcy J.M. Cain (darcy@druid) | D'Arcy Cain Consulting | I support gun control. West Hill, Ontario, Canada | Let's start with the government! + 416 281 6094 |
volpe@underdog.crd.ge.com (Christopher R Volpe) (10/19/90)
To everyone who responded: Thank you for the explanations and the Standard references. ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
chris@mimsy.umd.edu (Chris Torek) (10/19/90)
In article <2150@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >Now please excuse my almost total ignorance regarding the x3j11 >requirements regarding the contents of include files, but ... To aid in the confusion, note that ANSI C makes no requirements at all of this sort (since it nowhere requires that there be any files at all). The requirements are not `contents of include files' but rather `behaviour of the compiler upon seeing ``#include <stdio.h>'' ' (and other standard headers). If we consider `conventional Unix implementations', however: >I don't immediately see where (in 4.9.1) it says (explicitly) what >function are required to be declared within <stdio.h>. Are all of >the function listed in 4.9.4 thru 4.9.10 required to have declarations >within <stdio.h>? If so, are they required to have prototyped >declarations? Yes, and yes (unless the compiler implements them as `built in functions' that are somehow enabled by the `#include'). >... on a machine for which the va_list type is a structure ... I >encountered an odd problem. ... as it turned out, the creators of >the <stdio.h> file in question had cheated and put a declaration >like the following in it: > > int vfprintf (FILE *, const char *, void *); (but the type of `va_list' is not `void *'). >Obviously, that last formal parameter type is not correct! That's why I >got an error at the call. As it happens, `void *' is `good enough' to hold any pointer type. This machine's <stdio.h> contains a questionable, but legal, prototype for vfprintf (provided that it *works* of course). If the compiler generates warnings, it can still be considered ANSI conformant---the standard says nothing about excessive warnings. Nonetheless, I personally would like to know about such compilers that I might avoid them entirely. >I tried changing the last formal type to (a more correct) `va_list', but >when I did that this changed the <stdio.h> file into something that could >*not* be included ALL BY ITSELF into *any* given file. Rather, it now always >had to be preceeded by a #include <stdarg.h>. > >So what it the `correct' thing to have in the <stdio.h> file regarding the >vfprintf function (and friends)? This is one of those sticky implementation issues the ANSI standard leaves up to the implementor. Doug Gwyn has in the past suggested something along these lines: /* stdarg.h extract */ typedef int va_list[3]; /* stdio.h extract */ int vfprintf(FILE *, const char *, int *); where <stdio.h> `knows' what the stdarg.h va_list type is. This makes <stdio.h> machine-dependent; I consider this to be bad practise. The 4.3BSD-reno release <std*.h> headers use a different mechanism. A single file, <machine/machtypes.h>, contains all the machine-dependent type definitions, using the `hidden' (reserved to implementor) name space, and usually using preprocessor macros. For instance, the <machine/machtypes.h> for a VAX reads (abbreviated): #ifndef _MACHTYPES_H_ #define _MACHTYPES_H_ #define _PTRDIFF_T_ int /* ptr1 - ptr2 */ #define _VA_LIST_ char * /* va_list */ #define _WCHAR_T_ unsigned short /* wchar_t */ #define _SIZE_T_ unsigned int /* sizeof() */ #define _CLOCK_T_ unsigned long /* clock() */ #define _TIME_T_ long /* time() */ #endif and <stdio.h> then says, in part, #include <machine/machtypes.h> #ifdef _SIZE_T_ typedef _SIZE_T_ size_t; #undef _SIZE_T_ #endif /* some declarations deleted */ int vfprintf(FILE *, const char *, _VA_LIST_); while <stdarg.h>, in part, #include <machine/machtypes.h> typedef _VA_LIST_ va_list; On a machine requiring a pointer to a structure, <machine/machtypes.h> might read in part: typedef struct __va_list { /* contents */ } _VA_LIST_; and no changes to any of the machine-independent headers are necessary. The funny business with _SIZE_T_ is there so that <string.h> can also contain a typedef for size_t, yet including both <stdio.h> and <string.h> still works. SunOS 4.x releases have the typedefs done directly in a separate header, but this is erroneous, as it means that the following conforming program fragment fails to compile: #include <string.h> nlink_t(const char *s) { return (strlen(s) > 10); } -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/19/90)
In article <2150@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >Now please excuse my almost total ignorance regarding the x3j11 requirements >regarding the contents of include files, but I don't immediately see where >(in 4.9.1) it says (explicitly) what function are required to be declared >within <stdio.h>. Are all of the function listed in 4.9.4 thru 4.9.10 >required to have declarations within <stdio.h>? If so, are they required >to have prototyped declarations? Non-prototyped? Either? Section 4.1.2.1 says: "Each header declares or defines all identifiers listed in its associated section, ..." While it does not explicitly require that prototypes be used, a strictly conforming program must assume that the standard headers might use prototypes. Otherwise, it would be depending on undefined behavior. Of course it is expected that high-quality implementations WOULD use prototypes in the standard headers, because that would produce better diagnostic capabilities due to being able to check argument types. >... put a declaration like the following in it: > int vfprintf (FILE *, const char *, void *); >I tried changing the last formal type to (a more correct) `va_list', ... <stdio.h> must not rely on the inclusion of <stdarg.h> nor include <stdarg.h> itself. The v*() declarations in <stdio.h> should have the appropriate type directly used in the declaration (i.e. not via a typedef), or else they should use an implementation-reserved identifier for the typedef. For example: /* <stdio.h> example implementation (partial) */ #include <sys/cdefs> /* defines __va_list etc. */ /* [FILE defined here] */ int vfprintf(FILE *, const char *, __va_list); With this technique, the same file (<sys/cdefs>) can be used in the implementation of both <stdio.h> and <stdarg.h>.
steve@taumet.com (Stephen Clamage) (10/20/90)
rfg@NCD.COM (Ron Guilmette) writes:
!Now please excuse my almost total ignorance regarding the x3j11 requirements
!regarding the contents of include files, but I don't immediately see where
!(in 4.9.1) it says (explicitly) what function are required to be declared
!within <stdio.h>. Are all of the function listed in 4.9.4 thru 4.9.10
!required to have declarations within <stdio.h>? If so, are they required
!to have prototyped declarations? Non-prototyped? Either?
Section 4.1.2.1 says that a header must declare or define all identifiers
in its associated section. I find it hard to read the standard to say
that non-prototype declarations are OK, but that may be prejudice. I
haven't found an explicit statement that full prototypes are required.
! ... the creators of the <stdio.h> file in question had cheated
!and put a declaration like the following in it:
! int vfprintf (FILE *, const char *, void *);
!Obviously, that last formal parameter type is not correct!
Yes, they cheated, and this is not standard-conforming. The prototype
must match the one in the standard.
!I tried changing the last formal type to (a more correct) `va_list', but
!when I did that this changed the <stdio.h> file into something that could
!*not* be included ALL BY ITSELF into *any* given file. Rather, it now always
!had to be preceeded by a #include <stdarg.h>.
!So what it the `correct' thing to have in the <stdio.h> file regarding the
!vfprintf function (and friends)?
<stdio.h> cannot just #include <stdarg.h>, since no header may include
any of the others. The implementor cannot require you to #include
<stdarg.h> prior to <stdio.h>. The implementor must supply a prototype for
functions which are equivalent to using the typedefs in the non-included
header file. The implementor supplies all the headers, so this is
possible, apart from being required.
So in <stdarg.h> we might have:
struct _T { .... };
typedef struct _T va_list[2];
Then in <stdio.h> we would have:
struct _T;
int vfprintf(FILE *, const char*, struct _T*);
This meets all of the ANSI requirements.
--
Steve Clamage, TauMetric Corp, steve@taumet.com
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/21/90)
In article <483@taumet.com> steve@taumet.com (Stephen Clamage) writes: >! int vfprintf (FILE *, const char *, void *); >!Obviously, that last formal parameter type is not correct! >Yes, they cheated, and this is not standard-conforming. The prototype >must match the one in the standard. Presumably the declaration was correct for the implementation being used as a basis for modification by the original poster. I.e., I bet that void* was the type of va_list in that implementation. The spellings of the prototypes given in the standard need not be used in a conforming implementation; however, the types of the specified library functions, objects, etc. must be compatible with the ones in the standard. >Then in <stdio.h> we would have: > struct _T; > int vfprintf(FILE *, const char*, struct _T*); >This meets all of the ANSI requirements. I don't think so. You've given a parameter an incomplete type.
rfg@NCD.COM (Ron Guilmette) (10/22/90)
In article <27066@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes: <In article <2150@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: <>... on a machine for which the va_list type is a structure ... I <>encountered an odd problem. ... ... < <As it happens, `void *' is `good enough' to hold any pointer type. So what? <This machine's <stdio.h> contains a questionable, but legal, prototype <for vfprintf (provided that it *works* of course). If the compiler <generates warnings, it can still be considered ANSI conformant... The <stdio.h> contains what I feel is (or shoud be) an *illegal* prototype for vprintf(). Note that I said that on this particular machine, va_list is a *struct* type (*not* a pointer to struct type). Therefore, declaring the last parameter for vprintf() as a void* is certainly not going to work right. I just wanted to clarify that. -- // Ron Guilmette - C++ Entomologist // Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
rfg@NCD.COM (Ron Guilmette) (10/22/90)
In article <14195@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >Section 4.1.2.1 says: "Each header declares or defines all identifiers >listed in its associated section, ..." While it does not explicitly >require that prototypes be used, a strictly conforming program must >assume that the standard headers might use prototypes. Otherwise, it >would be depending on undefined behavior. Allow me to stray a bit from my original question (which has been adequately answer by a number of posters -- thank you all). If I understand you correctly Doug, you are saying that printf() could be declared in <stdio.h> in an unprototyped form (in a standard conforming implementation). This gives me pause. It seems that GCC (which is occasionally known to be standard conforming :-) will complain about: extern int foo (); extern int foo (int, ...); It says: problem.c:2: conflicting types for `foo' problem.c:2: A parameter list with an ellipsis can't match problem.c:2: an empty parameter name list declaration. problem.c:1: previous declaration of `foo' Therefore, I imagine that it would also complain about: extern int printf (); extern int printf (const char *, ...); Now if the first declaration was in <stdio.h> and if the second was in my (standard conforming?) program, I believe that GCC would also still complain (correctly, I believe). So if the declarations in `system' include files are allowed to be either prototyped or unprototyped, does this imply that my standard conforming programs must *not* contain (potentially conflicting) declarations for things which the standard requires be declared in any of the `system' include files which my program happens to include? ><stdio.h> must not rely on the inclusion of <stdarg.h> nor include ><stdarg.h> itself... I understand the `non-reliance' rule (and it even makes sense), but what about this second rule (i.e. that <stdio.h> cannot include <stdarg.h>)? I believe that such a rule exists, but just out of curiosity, which section of the standard is that rule given in? Also, what could be the reason for such a rule? Isn't it a bit superfluous? Could it not be trivially circumvented by placing all of the stuff that would normally go into <stdarg.h> into some other file (e.g. <foobar.h>) and then having both <stdio.h> and <stdarg.h> include <foobar.h>? -- // Ron Guilmette - C++ Entomologist // Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
chris@mimsy.umd.edu (Chris Torek) (10/22/90)
In article <2173@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >Note that I said that on this particular machine, va_list is a *struct* >type (*not* a pointer to struct type). Therefore, declaring the last >parameter for vprintf() as a void* is certainly not going to work right. True. I made the assumption that the system on that machine actually worked, and guessed (wrongly) that you dropped the `pointer to' somewhere along the line (easy to do in a Usenet posting where there is no compiler to catch such errors :-) ). I still find it hard to believe that someone would not test something as basic as vprintf (or at least vfprintf---in my implementation, all the printf routines eventually call vfprintf). This is sort of like sending a car to the dealer and forgetting to put in an engine. Surely *someone* would notice before selling the thing? -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
gwyn@smoke.BRL.MIL (Doug Gwyn) (10/23/90)
In article <2174@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >If I understand you correctly Doug, you are saying that printf() could >be declared in <stdio.h> in an unprototyped form (in a standard conforming >implementation). In some implementations it might work, not necessarily in all. >So if the declarations in `system' include files are allowed to be either >prototyped or unprototyped, does this imply that my standard conforming >programs must *not* contain (potentially conflicting) declarations for >things which the standard requires be declared in any of the `system' >include files which my program happens to include? A strictly conforming program must not misdeclare any of the standard library functions (consequence of 4.1.2.1). Also (see 4.1.6), special care must be taken if you both include the standard header and declare one of its functions yourself. >I understand the `non-reliance' rule (and it even makes sense), but what >about this second rule (i.e. that <stdio.h> cannot include <stdarg.h>)? >I believe that such a rule exists, but just out of curiosity, which section >of the standard is that rule given in? 4.1.2, 4.1.2.1. Note also that #include <...> syntax does not imply that any of the standard headers actually exist as files that look like pieces of C source code; thinking of the standard headers as included files is misleading. >Also, what could be the reason for such a rule? So that the programmer knows precisely what the effect of including a standard header will be. >Isn't it a bit superfluous? Could it not be trivially circumvented by >placing all of the stuff that would normally go into <stdarg.h> into >some other file (e.g. <foobar.h>) and then having both <stdio.h> and ><stdarg.h> include <foobar.h>? No, that wouldn't get around the problem of having #include <stdio.h> defining one or more va_* identifiers as a side effect, which is not allowed. A way to do this right has been described previously in this newsgroup.
henry@zoo.toronto.edu (Henry Spencer) (10/23/90)
In article <27098@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes: >I still find it hard to believe that someone would not test something >as basic as vprintf (or at least vfprintf---in my implementation, all >the printf routines eventually call vfprintf). This is sort of like >sending a car to the dealer and forgetting to put in an engine. Surely >*someone* would notice before selling the thing? Considering the number of things in (to pick purely random examples :-)) SVR4 and SunOS 4.1 that clearly were never tested, I fear Chris is being naive. Would that it were not so. -- The type syntax for C is essentially | Henry Spencer at U of Toronto Zoology unparsable. --Rob Pike | henry@zoo.toronto.edu utzoo!henry
poser@csli.Stanford.EDU (Bill Poser) (10/23/90)
In article <27098@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes: >I still find it hard to believe that someone would not test something >as basic as vprintf (or at least vfprintf---in my implementation, all >the printf routines eventually call vfprintf). This is sort of like >sending a car to the dealer and forgetting to put in an engine. Surely >*someone* would notice before selling the thing? One untested library function is nothing at all. I've seen a whole compiler that didn't work. Version 5.22 of HP-UX (probably others, but that's the one I know about for sure) had an F77 compiler that generated grossly incorrect assembler. The assembler gagged on EVERYTHING I tried. Obviously nobody had run the F77 compiler. Bill Poser
rfg@NCD.COM (Ron Guilmette) (10/28/90)
In article <27098@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes: <In article <2173@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: <>Note that I said that on this particular machine, va_list is a *struct* <>type (*not* a pointer to struct type). Therefore, declaring the last <>parameter for vprintf() as a void* is certainly not going to work right. < <True. I made the assumption that the system on that machine actually <worked... Just to clarify, the <stdio.h> file that contained the travesty that I described earlier was a part of somebody's broken version of an uncompleted U*IX-like system. It had not yet been fully tested and was not yet fully operational (as should be evident, based upon the brokenness of the <stdio.h> file). I apologize to all concerned if I gave you the impression that the bogus declaration for vprintf() that I described came out of a working system. It didn't. -- // Ron Guilmette - C++ Entomologist // Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.