home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / lang / c / 16207 < prev    next >
Encoding:
Text File  |  1992-11-09  |  3.5 KB  |  92 lines

  1. Path: sparky!uunet!stanford.edu!agate!dog.ee.lbl.gov!horse.ee.lbl.gov!torek
  2. From: torek@horse.ee.lbl.gov (Chris Torek)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Auto. conversion of function arguments
  5. Date: 9 Nov 1992 13:58:10 GMT
  6. Organization: Lawrence Berkeley Laboratory, Berkeley
  7. Lines: 79
  8. Message-ID: <27325@dog.ee.lbl.gov>
  9. References: <1229@jagubox.gsfc.nasa.gov>
  10. Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
  11. NNTP-Posting-Host: 128.3.112.15
  12.  
  13. In article <1229@jagubox.gsfc.nasa.gov> jim@jagubox.gsfc.nasa.gov
  14. (Jim Jagielski) writes:
  15. >Assume you have a function that accepts a char parameter. Now we know
  16. >that whenever an integral argument is passed by a function call, chars
  17. >and shorts are promoted to int...
  18.  
  19. This used to be the case.  Now, however, with ANSI C and prototypes,
  20. the picture has changed.
  21.  
  22. >Sooo... assuming you call a function that accepts 'char', is there any
  23. >_real_ reason why you must cast shorts and ints to char in the function
  24. >call itself?
  25.  
  26. There are three cases.
  27.  
  28.  A. The function is defined using old-style syntax:
  29.  
  30.     int f(c) char c; { ... }
  31.  
  32.  B. The function is defined using new prototype syntax, but at the
  33.     call site, the function is either not declared at all (and hence
  34.     gets implicitly declared), or is declared using old-style syntax.
  35.  
  36.  C. The function is defined using new prototype syntax, and is properly
  37.     (and fully) declared at the call site (i.e., the prototype is in
  38.     scope).
  39.  
  40. Now, if one or more of the arguments have `narrow' types (char, short,
  41. unsigned char, unsigned short, or float), case B is in fact a bug in
  42. the source, but not one that requires a diagnostic.  (A good compiler
  43. may be able to provide one anyway, but you cannot count on it.)
  44.  
  45. >After all, the parameter always "arrives" at the function as an int ...
  46.  
  47. In cases A and B, this is true.  In case C, it may or may not be true,
  48. depending on the implementation.  In case B, while the parameter
  49. actually arrives in widened form, the implementation may *expect* the
  50. narrow form; this is why case B is a program bug.  (If the
  51. implementation happens to use the widened form internally---for,
  52. say, backwards compatibility---then case B will `work' on that system,
  53. but it is still a program bug.)
  54.  
  55. Assuming that case B is no longer of interest (since the behavior of
  56. buggy programs is system-dependent), let us forge along with cases A
  57. and C.
  58.  
  59. >so it "appears" that another automatic conversion takes place:  from
  60. >the [widened type] that arrives to the [narrow] type of the parameter
  61.  
  62. True for case A; implementation-dependent for case C.
  63.  
  64. This means the code is guaranteed to work in case A.
  65.  
  66. In case C, the presence of the prototype causes the actual parameter to
  67. act as if it were an assignment.  In this case, even if the implementation
  68. really does use narrow parameters internally, the code must still work:
  69. the assignment causes conversion.
  70.  
  71. Thus, both of these complete fragments[%] are legal:
  72. -----
  73. % By this I mean more code is needed to make a complete program, but
  74.   these fragments are legal as a separate file, and when joined with
  75.   a legal main() must work.
  76. -----
  77.  
  78.     /* fragment 1 (compatible with truly ancient implementations) */
  79.     #include <stdio.h>
  80.  
  81.     callit() { (void)put('x'); }
  82.     int put(c) char c; { return fwrite(&c, 1, 1, stdout); }
  83.  
  84.     /* fragment 2 (for ANSI implementations) */
  85.     #include <stdio.h>
  86.  
  87.     int put(char c) { return fwrite(&c, 1, 1, stdout); }
  88.     void callit(void) { (void)put('x'); }
  89. -- 
  90. In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
  91. Berkeley, CA        Domain:    torek@ee.lbl.gov
  92.