amr@dukee.egr.duke.edu (Anthony M. Richardson) (02/07/90)
Can someone with access to the (proposed?) ANSI standard answer the following for me? Does the Standard specify what action should occur when old style function definitions are preceded by new style declarations? That is, if we have ======================= float foo(float, int); float foo(x, n) float x; int n; { ......... } ======================= what does the standard say about parameter conversions in this case? I see only three possible answers: (1) foo must assume that x will be passed as a float and must return a float, i.e. must obey the prototype, (2) the standard does not allow mixing of new style declarations and old style definitions, (3) behavior is implementation dependent. I guess there could be a (4): (4) foo must do old style parameter conversions (specifically float -> double), but this doesn't seem too likely. Email would be appreciated as I don't subscribe to this group. Thanks, Tony Richardson amr@dukee.egr.duke.edu
bright@Data-IO.COM (Walter Bright) (02/13/90)
In article <626@cameron.cs.duke.edu> amr@dukee.egr.duke.edu (Anthony M. Richardson) writes: < float foo(float, int); < < float foo(x, n) < float x; < int n; < { ......... } <what does the standard say about parameter conversions in this case? "Syntax error!" But seriously, the second definition is equivalent to: float foo(tmp,n) double tmp; int n; { float x = tmp; .... } Thus the syntax error. This and similar examples bite lots of code that is being converted to ANSI prototypes.
mark@Jhereg.Minnetech.MN.ORG (Mark H. Colburn) (02/13/90)
In article <2329@dataio.Data-IO.COM> bright@Data-IO.COM (Walter Bright) writes: >In article <626@cameron.cs.duke.edu> amr@dukee.egr.duke.edu (Anthony M. Richardson) writes: << float foo(float, int); << << float foo(x, n) << float x; << int n; << { ......... } <"Syntax error!" But seriously, the second definition is equivalent to: < < float foo(tmp,n) < double tmp; < int n; < { float x = tmp; < .... < } I was under the impression that the standard allowed parameters to be passed between functions without type coersion in this manner as long as there was a function prototype in effect. If no function prototype is in effect then the second example would be correct. However, using prototypes, the former should be correct. If you wanted doubles passed, you could always do: double foo(double, int); double foo(double x, int n) { ... }; -- Mark H. Colburn mark@Minnetech.MN.ORG Open Systems Architects, Inc.
raeburn@athena.mit.edu (Ken Raeburn) (02/14/90)
In article <1990Feb13.133503.19793@Jhereg.Minnetech.MN.ORG> mark@Jhereg.Minnetech.MN.ORG (Mark H. Colburn) writes: >In article <2329@dataio.Data-IO.COM> bright@Data-IO.COM (Walter Bright) writes: (basically that float foo (float, int); float foo (x, n) float x; int n; { /* ... */ } are incompatible, because the latter implies float foo (double arg_to_treat_as_float, int n)) >I was under the impression that the standard allowed parameters to be >passed between functions without type coersion in this manner as long >as there was a function prototype in effect. If no function prototype >is in effect then the second example would be correct. However, using >prototypes, the former should be correct. If you wanted doubles I had this argument a while back with a friend of mine from Lotus. As I recall, she was claiming that all of the ANSI C compilers she'd worked with except gcc did what you suggest. (I don't know which compilers or even which machines she was working with -- mostly in the PC world, I think -- but I hope not to have to use them.) But there is a section of the ANS (which I can't point you to, since I don't have my draft copy here) which says that the declaration implied by the old-style definition is compatible only with prototypes with (among other things) argument types that are compatible with the *promoted* type of the corresponding argument in the definition. The arguments I see basically go two ways: 1) Let's make the prototype not modify the behavior of the function. This way, the compiled function doesn't depend on whether the prototype was visible (and therefore providing more information) when the definition was compiled. (This is the course X3J11 chose.) 2) Let's make the prototype modify the function's behavior. This means that the definition does not contain all the information about the function that is needed to compile it. (Of course, to make life easier, we'll only require the prototype be in scope for the definition when you want to omit the default promotions.) This way, we can get exactly what we want with our new fancy ANSI-compliant compilers, and our old crufty compilers can still swallow the code (since we're using "#if __STDC__", of course!), even though they'll waste extra space in the argument list and so forth. I can make no claim as to what X3J11's reasoning was, but from at least one point of view, option 1 above seems sufficiently persuasive. (Of course, my friend held the opposite point of view, but....) -- Ken
walter@hpclwjm.HP.COM (Walter Murray) (02/15/90)
Mark H. Colburn writes: Concerning the example: ><< float foo(float, int); ><< ><< float foo(x, n) ><< float x; ><< int n; ><< { ......... } > I was under the impression that the standard allowed parameters to be > passed between functions without type coersion in this manner as long > as there was a function prototype in effect. That is true, but if you have a parameter of type float and you want to prevent promotion to double, both the declaration (if given) and the definition must use prototypes. This is a case where you can't mix a prototype declaration and an old-style definition. Walter ----------