Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!wuarchive!udel!princeton!notecnirp!nfs From: nfs@notecnirp.Princeton.EDU (Norbert Schlenker) Newsgroups: comp.lang.c Subject: Re: ANSI/Non-ANSI Function Declaration Macros Message-ID: <22402@princeton.Princeton.EDU> Date: 14 Dec 89 15:45:15 GMT References: <4603@itivax.iti.org> <244@isgtec.UUCP> Sender: news@princeton.Princeton.EDU Reply-To: nfs@notecnirp.UUCP (Norbert Schlenker) Distribution: na Organization: Dept. of Computer Science, Princeton University Lines: 58 In article <244@isgtec.UUCP| peter@isgtec.UUCP (Peter Curran) writes: |... |I have solved this problem in two parts. |1. Define a symbol PROTOTYPES as 1 if your current compiler supports | prototypes, 0 otherwise... |2. Define a macro P(x) as follows |#if PROTOTYPES |# define P(x) x |#else |# define P(x) () |# endif |3. Now you can declare functions as, for example | int foo P((FILE *file, int abc)); | Note the double parentheses - they are important. If PROTOTYPES | is 1, this preprocesses to | int foo (FILE *file, int abc): | Otherwise it preprocesses to | int foo (); | This is obviously uglier than using a real compiler, but only | three characters extra - a lot better than millions of #if's. |3. Write function headers in the old style: | |int foo (file, abc) |FILE *file; |int abc;.... | | This is obsolescent, but all standard-conforming compilers are | required to support it, and presumably will for the foreseeable | future. This means I get the benefits of prototypes whenever | possible, but can port to obsolete compilers without too much | pain. Of course, once UNIX catches up with the rest of the | world, I will abandoned the obsolescent form entirely. But there is a problem with this too! With a K&R compiler, things work just fine using this scheme. But with an ANSI compiler, any function taking a small argument (like char or short) will end up with a conflict between the prototype and the actual file header. For example: extern void func(char c, short n); void func(c, n) char c; short n; {} won't be accepted. The K&R definition is going to be treated as if it says: void func(c, n) int c; int n; {} since argument widening is automatic in K&R. Then there is a terrible mismatch between the prototype and the definition, which every ANSI compiler that I have seen complains bitterly about. So now you need to conditionally compile function headers, and that will always be less pleasant since it can't be done automagically by the preprocessor.