Path: utzoo!attcan!uunet!seismo!sundc!pitstop!sun!amdcad!ames!think!bloom-beacon!apple!rutgers!bellcore!tness7!ninja!sneaky!gordon From: gordon@sneaky.TANDY.COM (Gordon Burditt) Newsgroups: comp.sys.ibm.pc Subject: Re: Function declarations (was: MSC Summary: declaring function return values different in different places is unportable in the extreme Message-ID: <2416@sneaky.TANDY.COM> Date: 11 Sep 88 21:52:05 GMT References: <64@cybaswan.UUCP> <12400016@cpe> Organization: Gordon Burditt Lines: 89 In article <12400016@cpe>, tif@cpe.UUCP writes: > Written 6:40 pm Sep 4, 1988 by bigtex.UUCP!james in cpe:comp.sy.ibm.pc > >It's worse than all that. ANSI C permits conflicting function > >declarations without a warning - indeed it is required that no warning > >be given. ... Error: a diagnostic message that indicates that the program is non-conforming. Error messages are required by the standard under appropriate circumstances. Examples: "syntax error, line 127", "undeclared variable 'foo', line 64", and "include file 'foo.h' cannot be opened". Normally an error prohibits linking and execution of the program. Warning: a diagnostic message that does not indicate that the program is non-conforming. The presence of a warning must not prohibit the program from being run. ANSI C does not anywhere prohibit warnings for any idiotic or non-idiotic reason whatsoever: Warning - source program contains the character 'm'. Warning - use of single-character variable names - docking your paycheck $50.00 Warning - statement not reached Warning - source program contains the character 'a'. Compilation complete, 0 errors, 1 warnings, job cost $8.37 Warning - obscene variable name - naughty, naughty. Warning - implicit conversion from long to int may lose precision. Gag, barf, bletch - trigraphs used. Ick! Warning - indentation style does not match braces. Warning - numeric constant 3.14 is an inaccurate approximation for pi. Warning - division by three. Warning - numeric constant used - using a #define is preferred style. Warning - supplied MasterCard number is within $10.00 of credit limit. Warning - spelling error in comment. Warning - no warnings generated Warning - comments do not match code Warning - non-K&R I indentation style used Some existing compilers produce single-character warnings on every character in the code, paginated and with line numbers. This is sometimes referred to as a "compiler listing". > >... and I can't conceive of any > >implementation where the ANSI C requirement is actually useful. > I can. When you want to use a return value in more than one way. > a() { > int *malloc(), *x; > x = malloc(sizeof(int)); > } > > b() { > long *malloc(), *x; > x = malloc(sizeof(long)); > } At least one of these calls is likely to return garbage. Besides the problem that there is no guarantee that int * and long * have the same size, format, byte ordering, or bit ordering, every sane (read: how I would write it if my supply of drugs holds out :-) ) *86 compiler returns a (far) char * in ES:AX, and a (far) long * in ES:DX. Naturally, (far) unsigned char * is returned in AX:DX, and (far) unsigned long * in DX:AX. (far) int * is returned in BX:AX and short * is returned in CX:DX (Yes, even if short and int are the same size!) I think mismatched declarations like this ought to be a "common warning", even if it isn't an error. Regardless of what you think of the above linkage conventions, the implementer is still permitted to do this. Taking a more real example, on some 68000 implementations, pointers are returned in a0 and integers (of various sizes) are returned in d0. Since Berkeley and USG systems disagree over whether sprintf() returns the (char *) buffer given in the first argument or the (int) number of characters written in the buffer, someone wrote an assembly-language version of sprintf() that returned both values. Assuming that all programs that use the return value declare it correctly (dream on!), they could all get the expected return value. Cute, but unportable in the extreme! Another possibility for 8086 systems (which DO NOT have a protected mode!): Require that all structures and unions line up on a 16-byte boundary. Now, make a far struct pointer *16 BITS* - what you would load into the segment register to access it with an offset of 0. This is, of course, very different from the 16-bit near pointer, even if it is the same size. Pointers to ints, chars, etc. would still require at least a 24-bit (and probably 32-bit, for convenience of representation) far pointer. You could save some code making references like structptr->foo this way. Since it isn't upward-compatible to protected mode, compiler-writers aren't likely to do this. Gordon L. Burditt ...killer!ninja!sneaky!gordon