home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!stanford.edu!agate!dog.ee.lbl.gov!horse.ee.lbl.gov!torek
- From: torek@horse.ee.lbl.gov (Chris Torek)
- Newsgroups: comp.lang.c
- Subject: Re: Auto. conversion of function arguments
- Date: 9 Nov 1992 13:58:10 GMT
- Organization: Lawrence Berkeley Laboratory, Berkeley
- Lines: 79
- Message-ID: <27325@dog.ee.lbl.gov>
- References: <1229@jagubox.gsfc.nasa.gov>
- Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
- NNTP-Posting-Host: 128.3.112.15
-
- In article <1229@jagubox.gsfc.nasa.gov> jim@jagubox.gsfc.nasa.gov
- (Jim Jagielski) writes:
- >Assume you have a function that accepts a char parameter. Now we know
- >that whenever an integral argument is passed by a function call, chars
- >and shorts are promoted to int...
-
- This used to be the case. Now, however, with ANSI C and prototypes,
- the picture has changed.
-
- >Sooo... assuming you call a function that accepts 'char', is there any
- >_real_ reason why you must cast shorts and ints to char in the function
- >call itself?
-
- There are three cases.
-
- A. The function is defined using old-style syntax:
-
- int f(c) char c; { ... }
-
- B. The function is defined using new prototype syntax, but at the
- call site, the function is either not declared at all (and hence
- gets implicitly declared), or is declared using old-style syntax.
-
- C. The function is defined using new prototype syntax, and is properly
- (and fully) declared at the call site (i.e., the prototype is in
- scope).
-
- Now, if one or more of the arguments have `narrow' types (char, short,
- unsigned char, unsigned short, or float), case B is in fact a bug in
- the source, but not one that requires a diagnostic. (A good compiler
- may be able to provide one anyway, but you cannot count on it.)
-
- >After all, the parameter always "arrives" at the function as an int ...
-
- In cases A and B, this is true. In case C, it may or may not be true,
- depending on the implementation. In case B, while the parameter
- actually arrives in widened form, the implementation may *expect* the
- narrow form; this is why case B is a program bug. (If the
- implementation happens to use the widened form internally---for,
- say, backwards compatibility---then case B will `work' on that system,
- but it is still a program bug.)
-
- Assuming that case B is no longer of interest (since the behavior of
- buggy programs is system-dependent), let us forge along with cases A
- and C.
-
- >so it "appears" that another automatic conversion takes place: from
- >the [widened type] that arrives to the [narrow] type of the parameter
-
- True for case A; implementation-dependent for case C.
-
- This means the code is guaranteed to work in case A.
-
- In case C, the presence of the prototype causes the actual parameter to
- act as if it were an assignment. In this case, even if the implementation
- really does use narrow parameters internally, the code must still work:
- the assignment causes conversion.
-
- Thus, both of these complete fragments[%] are legal:
- -----
- % By this I mean more code is needed to make a complete program, but
- these fragments are legal as a separate file, and when joined with
- a legal main() must work.
- -----
-
- /* fragment 1 (compatible with truly ancient implementations) */
- #include <stdio.h>
-
- callit() { (void)put('x'); }
- int put(c) char c; { return fwrite(&c, 1, 1, stdout); }
-
- /* fragment 2 (for ANSI implementations) */
- #include <stdio.h>
-
- int put(char c) { return fwrite(&c, 1, 1, stdout); }
- void callit(void) { (void)put('x'); }
- --
- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
- Berkeley, CA Domain: torek@ee.lbl.gov
-