Path: utzoo!utgpu!watserv1!watmath!att!att!dptg!ulysses!andante!mit-eddie!snorkelwacker!usc!wuarchive!udel!haven!mimsy!chris From: chris@mimsy.umd.edu (Chris Torek) Newsgroups: comp.std.c Subject: Re: prototypes required ? Keywords: printf stdargs prototypes Message-ID: <27066@mimsy.umd.edu> Date: 19 Oct 90 14:07:35 GMT References: <4026@otis.oakhill.UUCP> <14164@smoke.BRL.MIL> <2150@lupine.NCD.COM> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 112 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 '' ' (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 . Are all of >the function listed in 4.9.4 thru 4.9.10 required to have declarations >within ? 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 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 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 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 . > >So what it the `correct' thing to have in the 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 `knows' what the stdarg.h va_list type is. This makes machine-dependent; I consider this to be bad practise. The 4.3BSD-reno release headers use a different mechanism. A single file, , contains all the machine-dependent type definitions, using the `hidden' (reserved to implementor) name space, and usually using preprocessor macros. For instance, the 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 then says, in part, #include #ifdef _SIZE_T_ typedef _SIZE_T_ size_t; #undef _SIZE_T_ #endif /* some declarations deleted */ int vfprintf(FILE *, const char *, _VA_LIST_); while , in part, #include typedef _VA_LIST_ va_list; On a machine requiring a pointer to a structure, 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 can also contain a typedef for size_t, yet including both and 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 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