Can a static function declaration conflict with a non-static declaration?

Discussion in 'C Programming' started by nospam_timur@tabi.org, Dec 12, 2006.

  1. Guest

    Let's say I have two files, myfile.h and myfile.c:

    myfile.h:

    int myfunction(int x);

    myfile.c:

    #include "myfile.h"

    static int myfunction(char *x)
    {
    return 0;
    }

    Does this conform to the C standard? With GCC 4, this generates an
    error, because the definitions of myfunction() conflict. I have a
    colleague who says this compiles in GCC 3, because the static version
    of myfunction() overrides the non-static prototype from the header
    file. I believe that GCC 3 is just ignoring the problem, and that it's
    technically a bug, but I can't find any documentation that specifically
    says that static and non-static declarations of the same function have
    to have the same parameters and return type.
    , Dec 12, 2006
    #1
    1. Advertising

  2. Chris Torek Guest

    In article <>
    <> wrote:
    >Let's say I have two files, myfile.h and myfile.c:
    >
    >myfile.h:
    >
    >int myfunction(int x);
    >
    >myfile.c:
    >
    >#include "myfile.h"
    >
    >static int myfunction(char *x)
    >{
    > return 0;
    >}
    >
    >Does this conform to the C standard?


    6.1.2.2 Linkages of identifiers
    [snippage]
    [#7] If, within a translation unit, the same identifier
    appears with both internal and external linkage, the
    behavior is undefined.

    The first declaration, in myfile.h (first because it is #include-d
    before the second declaration) does not use the "extern" keyword and
    has no previous declaration in scope, so it specifies external linkage
    for the identifier "myfunction".

    The second declaration, using the "static" keyword, specifies internal
    linkage for the identifier "myfunction".

    The behavior is undefined.

    >With GCC 4, this generates an error, because the definitions of
    >myfunction() conflict.


    Allowed, since the behavior is undefined.

    >I have a colleague who says this compiles in GCC 3, because the
    >static version of myfunction() overrides the non-static prototype
    >from the header file.


    Also allowed, since the behavior is undefined.

    GCC 4's complaint is probably a good idea, since relying on undefined
    behavior when "well-defined behavior" is at least as good is unwise.
    (Using undefined behavior for positive benefit, in places where
    "well-defined behavior" is no good, is another matter entirely.
    That is, I would not call it "unwise" to "#include <graphics.h>"
    in order to draw graphics on a screen or window. The cost --
    behavior undefined by a widespread standard -- is outweighed by
    the benefit of being able to do what the code is required to do.
    But here there is no benefit from mixing internal and external
    linkage, only a cost.)

    >I believe that GCC 3 is just ignoring the problem, and that it's
    >technically a bug, but I can't find any documentation that specifically
    >says that static and non-static declarations of the same function have
    >to have the same parameters and return type.


    Since the behavior is undefined, anything can happen.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Dec 12, 2006
    #2
    1. Advertising

  3. Ben Pfaff Guest

    Chris Torek <> writes:

    > In article <>
    > <> wrote:
    >>Let's say I have two files, myfile.h and myfile.c:
    >>
    >>myfile.h:
    >>
    >>int myfunction(int x);
    >>
    >>myfile.c:
    >>
    >>#include "myfile.h"
    >>
    >>static int myfunction(char *x)
    >>{
    >> return 0;
    >>}
    >>
    >>Does this conform to the C standard?

    >
    > 6.1.2.2 Linkages of identifiers
    > [snippage]
    > [#7] If, within a translation unit, the same identifier
    > appears with both internal and external linkage, the
    > behavior is undefined.
    >
    > The first declaration, in myfile.h (first because it is #include-d
    > before the second declaration) does not use the "extern" keyword and
    > has no previous declaration in scope, so it specifies external linkage
    > for the identifier "myfunction".
    >
    > The second declaration, using the "static" keyword, specifies internal
    > linkage for the identifier "myfunction".
    >
    > The behavior is undefined.


    I agree.

    However, it may be worth adding that the opposite situation,
    shown below, is OK:

    static int myfunction(void);
    int myfunction(void) {
    ...
    }

    This is because there is an explicit exception for this situation
    in the Standard:

    For an identifier declared with the storage-class specifier
    extern in a scope in which a prior declaration of that
    identifier is visible,23) if the prior declaration specifies
    internal or external linkage, the linkage of the identifier
    at the later declaration is the same as the linkage
    specified at the prior declaration. If no prior declaration
    is visible, or if the prior declaration specifies no
    linkage, then the identifier has external linkage.

    --
    Just another C hacker.
    Ben Pfaff, Dec 12, 2006
    #3
  4. Chris Torek Guest

    In article <>
    Ben Pfaff <> wrote (in part):
    >... it may be worth adding that the opposite situation,
    >shown below, is OK:
    >
    > static int myfunction(void);
    > int myfunction(void) {
    > ...
    > }
    >
    >This is because there is an explicit exception for this situation
    >in the Standard:
    >
    > For an identifier declared with the storage-class specifier
    > extern in a scope in which a prior declaration of that
    > identifier is visible,23) if the prior declaration specifies
    > internal or external linkage, the linkage of the identifier
    > at the later declaration is the same as the linkage
    > specified at the prior declaration. If no prior declaration
    > is visible, or if the prior declaration specifies no
    > linkage, then the identifier has external linkage.


    The exception quoted here is specific to declarations using the
    "extern" keyword. So, this means:

    static int myfunction(void);
    extern int myfunction(void) {
    ...
    }

    is OK. So is:

    static double d;
    extern double d;

    In these two cases, the "extern" keyword functions the same as the
    "static" keyword, giving the identifier internal linkage.

    Omitting the "extern" keyword entirely is even more bizarre:

    [#5] If the declaration of an identifier for a function has
    no storage-class specifier, its linkage is determined
    exactly as if it were declared with the storage-class
    specifier extern. If the declaration of an identifier for
    an object has file scope and no storage-class specifier, its
    linkage is external.

    Note the different specifications for functions vs objects. This
    means Ben Pfaff's example (a function) is OK: with no storage class
    specifier keyword, the function inherits the linkage of the visible
    prior declaration (i.e., the "static" one right above it) -- but
    my example with "d" above becomes invalid if the "extern" keyword
    is removed:

    static double d;
    double d; /* ERROR */

    I have no idea why this particular (apparently entirely gratuitous)
    inconsistency exists in the C standards.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Dec 12, 2006
    #4
  5. In article <>,
    Chris Torek <> wrote:

    >Omitting the "extern" keyword entirely is even more bizarre:
    >
    > [#5] If the declaration of an identifier for a function has
    > no storage-class specifier, its linkage is determined
    > exactly as if it were declared with the storage-class
    > specifier extern. If the declaration of an identifier for
    > an object has file scope and no storage-class specifier, its
    > linkage is external.
    >
    >Note the different specifications for functions vs objects. This
    >means Ben Pfaff's example (a function) is OK: with no storage class
    >specifier keyword, the function inherits the linkage of the visible
    >prior declaration (i.e., the "static" one right above it) -- but
    >my example with "d" above becomes invalid if the "extern" keyword
    >is removed:
    >
    > static double d;
    > double d; /* ERROR */
    >
    >I have no idea why this particular (apparently entirely gratuitous)
    >inconsistency exists in the C standards.


    Presumably it's related to the fact that

    double d;

    is all you need to do to cause a double to exist, but

    int myfunction(void);

    still leaves you in need of the definition. There's no default
    initializer for functions! The only use of a function declaration
    without a body is to declare the function's interface, so why require
    the user to add a redundant "extern"?

    -- Richard

    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
    Richard Tobin, Dec 12, 2006
    #5
    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. Replies:
    2
    Views:
    507
    Jonathan Mcdougall
    Aug 6, 2007
  2. dolphin
    Replies:
    3
    Views:
    1,328
    Pete Becker
    Dec 5, 2007
  3. charles cashion

    css conflict (or html conflict)

    charles cashion, Feb 18, 2009, in forum: HTML
    Replies:
    2
    Views:
    780
    charles cashion
    Feb 18, 2009
  4. rickman
    Replies:
    5
    Views:
    416
    rickman
    Mar 30, 2013
  5. junyangzou
    Replies:
    3
    Views:
    187
    Victor Bazarov
    Aug 21, 2013
Loading...

Share This Page