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

  • Follow


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.

0
Reply nospam_timur (23) 12/12/2006 4:52:28 PM

In article <1165942348.630550.196270@n67g2000cwd.googlegroups.com>
nospam_timur@tabi.org <timur@tabi.org> 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.
0
Reply nospam252 (1722) 12/12/2006 7:54:22 PM


Chris Torek <nospam@torek.net> writes:

> In article <1165942348.630550.196270@n67g2000cwd.googlegroups.com>
> nospam_timur@tabi.org <timur@tabi.org> 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.
0
Reply blp (3953) 12/12/2006 8:44:53 PM

In article <87bqm8x2re.fsf@blp.benpfaff.org>
Ben Pfaff  <blp@cs.stanford.edu> 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.
0
Reply nospam252 (1722) 12/12/2006 9:26:01 PM

In article <eln6p9029gq@news2.newsguy.com>,
Chris Torek  <nospam@torek.net> 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.
0
Reply richard91 (3683) 12/12/2006 10:26:52 PM

4 Replies
46 Views

(page loaded in 0.084 seconds)

Similiar Articles:
















6/21/2012 8:34:46 AM


Reply: