new style declarations OK for old style definitions?

Discussion in 'C Programming' started by john, Jun 21, 2010.

  1. john

    john Guest

    K&R/2 is a little vague on the following question: under what
    circumstances is it legal to declare using new-style syntax a
    separately compiled function that was compiled with an old-style
    definition.

    Is it sufficient to use only promoted arguments in the new-style
    declaration?

    Conceivably, the whole calling sequence for old style and new style
    definitions could differ. Is it legal for the compiler to choose
    completely incompatible calling sequences for old-style and new-style
    declarations? It would certainly be desirable, since new-style
    declarations seem to allow for significant optimizations that aren't
    possible with old-style declarations.

    This is a frequent problem if you have old library binaries and
    sources but want the extra type checking from an ANSI compiler.

    Thanks
    john, Jun 21, 2010
    #1
    1. Advertising

  2. john

    Eric Sosman Guest

    On 6/21/2010 2:55 PM, john wrote:
    > K&R/2 is a little vague on the following question: under what
    > circumstances is it legal to declare using new-style syntax a
    > separately compiled function that was compiled with an old-style
    > definition.
    >
    > Is it sufficient to use only promoted arguments in the new-style
    > declaration?


    I believe so, but I can't find an explicit statement to that
    effect in the Standard. There's a highly suggestive example in
    6.2.7p5, but examples are non-normative. 6.5.2.2p6 addresses a
    related but not identical situation, and 6.5.2.2p7 doesn't quite
    nail the whole thing down.

    As far as I know, there's no way to determine the type to
    which an enum variable promotes (enum named constants are always
    of type int, but an enum variable need not be; 6.7.2.2p4). And
    there's probably no safe way to call an old-style variadic function;
    if you prototype it with ,...) you'll get calls that are appropriate
    for the <stdarg.h> machinery, whereas the old-style function is
    likely using the non-portable pre-Standard <varargs.h>. Best bet
    is probably to cross your fingers and hope the compiler never changes,
    or to discard and rewrite the function.

    One possibility, if you're really interested in policing things,
    might be to write new-style wrappers for the old-style functions and
    insist that people use the wrappers instead of making direct calls.
    (Some `#define oldfunc %%% please use newfunc instead %%%' lines may
    be helpful here.) This way, you can limit the scope of your worries
    to the wrappers themselves rather than to an entire body of code.

    > Conceivably, the whole calling sequence for old style and new style
    > definitions could differ. Is it legal for the compiler to choose
    > completely incompatible calling sequences for old-style and new-style
    > declarations? It would certainly be desirable, since new-style
    > declarations seem to allow for significant optimizations that aren't
    > possible with old-style declarations.


    As I said, I can't find an explicit prohibition. Still, it
    seems unlikely that new- and old-style fixed-argument functions
    would have different calling conventions. The only optimizations
    I can think of would be avoiding needless promote-demote pairs
    (e.g., float to double in the caller, double back to float in
    the callee), but those should "fall out" of the extra knowledge
    the prototype supplies.

    > This is a frequent problem if you have old library binaries and
    > sources but want the extra type checking from an ANSI compiler.


    If you've got ancient binaries you may have additional trouble.
    What I've written above applies to new- and old-style functions as
    compiled by a modern compiler; a pre-Standard compiler for a pre-
    Standard dialect of C may be doing a lot of surprising things ...

    --
    Eric Sosman
    lid
    Eric Sosman, Jun 21, 2010
    #2
    1. Advertising

  3. john

    john Guest

    john wrote:

    > K&R/2 is a little vague on the following question: under what
    > circumstances is it legal to declare using new-style syntax a separately
    > compiled function that was compiled with an old-style definition.
    >
    > Is it sufficient to use only promoted arguments in the new-style
    > declaration?
    >
    > Conceivably, the whole calling sequence for old style and new style
    > definitions could differ. Is it legal for the compiler to choose
    > completely incompatible calling sequences for old-style and new-style
    > declarations? It would certainly be desirable, since new-style
    > declarations seem to allow for significant optimizations that aren't
    > possible with old-style declarations.
    >
    > This is a frequent problem if you have old library binaries and sources
    > but want the extra type checking from an ANSI compiler.
    >
    > Thanks


    * bump *
    john, Jun 21, 2010
    #3
  4. john

    john Guest

    Eric Sosman wrote:
    < snip >

    Thanks Eric.

    Seeing as new C is backwards compatable, I sometimes wonder if it
    wouldn't be easier just to write new code in K&R1 style and avoid all the
    problems of inter-operability... I guess the ANSI standard buys you a few
    nice features though.
    john, Jun 21, 2010
    #4
  5. john

    Seebs Guest

    On 2010-06-21, john <> wrote:
    > Seeing as new C is backwards compatable,


    Mostly. Often.

    > I sometimes wonder if it
    > wouldn't be easier just to write new code in K&R1 style and avoid all the
    > problems of inter-operability... I guess the ANSI standard buys you a few
    > nice features though.


    That would have been a great theory around 1987. Now, you should never
    write anything in K&R1 style without a very specific reason to imagine that
    you care about a compiler over twenty years old.

    The argument checking, plus the ability to pass some types of arguments
    at all, are big wins.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    Seebs, Jun 21, 2010
    #5
  6. john

    Eric Sosman Guest

    On 6/21/2010 3:57 PM, john wrote:
    > Eric Sosman wrote:
    > < snip>
    >
    > Thanks Eric.
    >
    > Seeing as new C is backwards compatable, I sometimes wonder if it
    > wouldn't be easier just to write new code in K&R1 style and avoid all the
    > problems of inter-operability... I guess the ANSI standard buys you a few
    > nice features though.


    ... for example, the prototypes you're struggling to write! IMHO,
    the greatest benefit of the C89/C90 Standard was that it provided a
    language definition that amounted to more than "Whatever my compiler
    does is right." That pre-Standard definition led to divergent dialects,
    greater porting expenses, and "Our way is better" from pretty much all
    compiler suppliers. The Standard scotched most of these arguments and
    gave all suppliers a common target to aim at -- there remain the areas
    the Standard deliberately doesn't cover or governs only in part, and the
    areas where the Standard's language is open to misunderstanding, but by
    and large I feel the single greatest benefit of the Standard was, well,
    standardization.

    Prototyped function definitions and declarations, though, run a
    close second in the adding-value sweepstakes. In the Bad Old Days it
    was depressingly common to find `int f(a,b) int a,b; {...}' called
    as `f(42)'. Quite often the error would go undetected even at run time
    if a plausible `b' value just happened to be in the right register or at
    the right stack offset or whatever -- until you cranked up the optimizer
    and all Hell broke loose, or until you upgraded the compiler and ditto,
    or until you merely changed a few addresses by re-linking and ditto, or
    (most especially) when you ported the code to another machine and heard
    the bells of Hell peal for sheer joy of deviltry. Function prototypes
    are a *huge* benefit and cost-saver; they're "nice features" the same
    way polio vaccine is a "nice feature."

    --
    Eric Sosman
    lid
    Eric Sosman, Jun 21, 2010
    #6
  7. john <> writes:
    > john wrote:
    >

    [question snipped]
    >
    > * bump *


    It looks like you posted a followup, quoting your original question
    and adding only "* bump *", in an effort to raise the visibility
    of your question. You did this less than an hour after you posted.

    Please don't do that here. I've seen web forums where that kind
    of thing makes sense, but this is a newsgroup. Generally the
    set of articles that are visible to a given reader is specific to
    that reader, based on what the reader has already read and on the
    reader's personal preferences. Trying to mess with that is likely
    to be counterproductive.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 21, 2010
    #7
  8. john

    Tim Rentsch Guest

    john <> writes:

    > K&R/2 is a little vague on the following question: under what
    > circumstances is it legal to declare using new-style syntax a
    > separately compiled function that was compiled with an old-style
    > definition.
    >
    > Is it sufficient to use only promoted arguments in the new-style
    > declaration?


    The relevant paragraph is 6.7.5.3p15. Note in particular the
    second-to-last sentence.

    For two function types to be compatible, both shall specify
    compatible return types(127). Moreover, the parameter type
    lists, if both are present, shall agree in the number of
    parameters and in use of the ellipsis terminator; corresponding
    parameters shall have compatible types. If one type has a
    parameter type list and the other type is specified by a function
    declarator that is not part of a function definition and that
    contains an empty identifier list, the parameter list shall not
    have an ellipsis terminator and the type of each parameter shall
    be compatible with the type that results from the application of
    the default argument promotions. If one type has a parameter
    type list and the other type is specified by a function
    definition that contains a (possibly empty) identifier list, both
    shall agree in the number of parameters, and the type of each
    prototype parameter shall be compatible with the type that
    results from the application of the default argument promotions
    to the type of the corresponding identifier. (In the
    determination of type compatibility and of a composite type, each
    parameter declared with function or array type is taken as having
    the adjusted type and each parameter declared with qualified type
    is taken as having the unqualified version of its declared type.)

    with footnote (127):

    If both function types are ``old style'', parameter types are not
    compared.


    > Conceivably, the whole calling sequence for old style and new style
    > definitions could differ.


    Under ISO C they cannot. As long as the declaration (with prototype)
    is compatible with the type at the definition -- regardless of whether
    it is "old style" or "new style" -- the declaration is legal and calls
    matching the declaration must work, no matter how the function is
    defined, and since the compiler doesn't know how it's defined, the
    calling sequences for the two cases must be the same.

    > Is it legal for the compiler to choose
    > completely incompatible calling sequences for old-style and new-style
    > declarations?


    Only in the sense that it's possible to jigger up all sorts of strange
    things under the "as if" rule. Practically speaking, no compiler
    would ever go to such lengths, because calls in the two cases must
    behave identically. Not only that, but taking the address of a
    function using '&' produces a pointer-to-function that must behave
    identically for the two cases. There is just no reasonable way to
    do this in a standard compilation environment where the function in
    question is defined in another translation unit.


    > It would certainly be desirable, since new-style
    > declarations seem to allow for significant optimizations that aren't
    > possible with old-style declarations.


    I guess it's possible that this is right, but it's the wrong question.
    The question is, if we have a new style _declaration_, does it make
    sense to use different calling sequences for a new style _definition_
    vs an old style _definition_. The new style _declaration_ gives us
    all the information we need to do any possible optimizations in both
    cases. At the point of _definition_, there is enough information
    available to construct a new style _declaration_, and that allows
    all the optimizations that would be possible if the definition were
    written using a prototype.

    Remember: functions defined with prototypes (assuming they meet
    certain criteria as regards which types are present, use of ellipsis,
    etc) must be callable using either new style or old style declarations.
    Because we don't know (in those cases that meet the criteria) whether
    the declaration style matches the definition style, and all four cases
    must work the same way, there's no useful way to differentiate in
    general.


    > This is a frequent problem if you have old library binaries and
    > sources but want the extra type checking from an ANSI compiler.


    If you're compiling the (old style) sources, a good sanity check
    is to write new-style declarations (ie the same ones that you're
    using to compile the other code) and arrange to have those be
    present in the source before the old style function definitions.
    (Can be done as compilations "on the side" if necessary.) This
    way, if the prototypes don't match the definitions, the compiler
    will squawk, and you'll know the prototype is no good. But if
    the old style definition is accepted with a prototype declared
    before it, then the old style definition is going to work when
    called using that prototype declaration.
    Tim Rentsch, Jun 22, 2010
    #8
  9. On 21 June, 20:57, john <> wrote:

    > Seeing as new C is backwards compatable, I sometimes wonder if it
    > wouldn't be easier just to write new code in K&R1 style and avoid all the
    > problems of inter-operability... I guess the ANSI standard buys you a few
    > nice features though.


    do you actually have some K&R code you have to interface with?
    Nick Keighley, Jun 22, 2010
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rikard Land
    Replies:
    0
    Views:
    345
    Rikard Land
    Oct 19, 2004
  2. Steven T. Hatton

    Declarations and Definitions in One Header

    Steven T. Hatton, Apr 25, 2004, in forum: C++
    Replies:
    4
    Views:
    324
    Steven T. Hatton
    Apr 25, 2004
  3. Chris Gordon-Smith

    Declarations and Definitions: Grammar

    Chris Gordon-Smith, Oct 3, 2004, in forum: C++
    Replies:
    2
    Views:
    366
    Gary Labowitz
    Oct 3, 2004
  4. Kobu

    old style function definitions

    Kobu, Feb 11, 2005, in forum: C Programming
    Replies:
    5
    Views:
    351
    Chris Torek
    Feb 11, 2005
  5. Huibert Bol

    Re: identifier scope in old-style declarations

    Huibert Bol, Aug 6, 2008, in forum: C Programming
    Replies:
    12
    Views:
    581
Loading...

Share This Page