Xref: utzoo gnu.gcc.bug:1056 gnu.gcc:502 comp.std.c:1167 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!rutgers!mit-eddie!uw-beaver!uw-june!ka From: ka@june.cs.washington.edu (Kenneth Almquist) Newsgroups: gnu.gcc.bug,gnu.gcc,comp.std.c Subject: Re: gcc 1.35 conflicting types message? Message-ID: <8141@june.cs.washington.edu> Date: 8 May 89 07:04:39 GMT References: <9101@elsie.UUCP> <8124@june.cs.washington.edu> <2867@cps3xx.UUCP> Organization: U of Washington, Computer Science, Seattle Lines: 77 >ado@elsie.UUCP (Arthur David Olson) writes: (paraphrased) >>gcc v. 1.35 generates a "conflicting types" message >>and refuses to compile when confronted with code such as. . . >> >> extern int whatever(); >> extern int whatever(char * format, ...); That's because these are incompatible. Bear with me for a few paragraphs of explanation. In traditional C, the number of arguments was not known at compile time. If a subroutine declared three arguments you could pass it four arguments. More usefully, you could pass the routine only two arguments if you knew that it was going to only reference its first two arguments on a particular call. This feature of C made some people unhappy because the "natural" calling sequence on some architectures requires a procedure to know how many arguments it was called with. An example is the 8086, where the "return from subroutine" instruction pops the arguments to the subroutine off the stack. C compilers for the 8086 and similar architectures have had to use a nonstandard calling sequences that do not require the callee to know the number of arguments. Two problems with using nonstandard calling sequences are: 1) It is likely to make function calls slower, and 2) It makes interfacing to code written in other languages more difficult. These problems (and possibly others) persuaded ANSI to require that the actual number of arguments be the same as the number of arguments declared, with the exception of functions which are explicitly declared to be varadic. (Apparently even thousands of PC users couldn't convince ANSI to eliminate printf. :-)) In other words, compilers are still required to support a form of subroutine call linkage which can handle a varying number of arguments, but they are only required to use this for procedures which are explicitly declared varadic. For other procedures, they are allowed to use calling conventions which require the called procedure to know the number of arguments at compile time. If a compiler takes advantage of this, then the compiler *must* know whether a function is varadic or not when it generates a call to that function. For example, consider following program: main() { printf("Hello, world\n"); exit(0); } This program is legal in traditional C, but in ANSI C all sorts of nasty things can happen. For example, on some machines it might make sense to have the callee *always* pop the arguments off the stack, and have the caller pass in the number of arguments when the function is varadic. In this case, the printf routine will treat the "hello, world\n" string as the number of arguments, and treat the next argument (which doesn't exist) as the format string. This will cause it to print out a bunch of garbage, pop some huge number of arguments off the stack (since the address of the "hello, world" string is likely to be a fairly large number), and return. When the program tries to call "exit" the stack pointer may very well be pointing at nonexistent memory, causing a core dump. I expect that an implementation which behaved like this would not sell very well, but it would conform to ANSI C. So to return to the original question, if you write >> extern int printf(); this tells the C compiler that printf is not a varadic function. The subsequent declaration >> extern int printf(char * format, ...); tells the C compiler that printf *is* a varadic function. Since the compiler may need to know whether or not printf is varadic in order to generate a call to it, giving the compiler conflicting information is rightly made illegal. Kenneth Almquist