static in front of function declared locally

Discussion in 'C Programming' started by maxw_cc, Jun 30, 2003.

  1. maxw_cc

    maxw_cc Guest

    Hello everybody,

    To express my question, I will help myself
    with the following simple snippet
    (all functions residing in the same file):


    /** stat_fn.c **/

    #include <stdio.h>

    void foo1(void)
    {
    void foo2(void);

    printf("foo1\n");
    foo2();
    }

    static void foo2(void)
    {
    printf("foo2\n");
    }

    int main(void)
    {
    foo1();

    return 0;
    }

    When I compile it using gcc I get:

    $ gcc -g -Wall -ansi -pedantic -o stat_fn stat_fn.c
    stat_fn.c:12: warning: `foo2' was declared `extern' and later `static'

    And then I thought, maybe changing the declaration for foo2()
    withing foo1() to 'static void foo2(void);' would silence the
    warning. Then the new file would look like this:

    /** stat_fn1.c **/

    #include <stdio.h>

    void foo1(void)
    {
    static void foo2(void);

    printf("foo1\n");
    foo2();
    }

    static void foo2(void)
    {
    printf("foo2\n");
    }

    int main(void)
    {
    foo1();

    return 0;
    }

    But to my surprise now I got the following:

    $ gcc -g -Wall -ansi -pedantic -o stat_fn1 stat_fn1.c
    stat_fn1.c: In function `foo1':
    stat_fn1.c:5: warning: invalid storage class for function `foo2'

    Why is 'static' an invalid storage class for function `foo2' in
    the declaration for foo2() embedded in foo1()?

    After that I found out, that one way to silence all warnings was to
    put the declaration for foo2() at file scope, like this:


    /** stat_fn2.c **/

    #include <stdio.h>

    static void foo2(void);

    void foo1(void)
    {
    printf("foo1\n");
    foo2();
    }

    static void foo2(void)
    {
    printf("foo2\n");
    }

    int main(void)
    {
    foo1();

    return 0;
    }


    And now zero warnings appeared...

    Does this mean that I cannot declare a function with the storage
    class 'static' if this declaration is local to a function?
    What does the standard say about this?

    Any light on this matter will be highly appreciated...

    Thanks a lot in advance...

    Max
     
    maxw_cc, Jun 30, 2003
    #1
    1. Advertisements

  2. maxw_cc

    Chris Lowth Guest

    "static" means "can only be seen in this context" when set at the global
    level, but means something like "data item that retains its value" when
    declared inside a function (ie: does not live on the stack). This second
    meaning doesnt make sense for a function declaration.

    The confusion is this double meaning of the keyword "static".

    The right way to do this is either declare foo2 before foo1 or use a "pre
    declaration" as you have in your last example.

    Chris
     
    Chris Lowth, Jun 30, 2003
    #2
    1. Advertisements

  3. maxw_cc

    John Smith Guest

    In your first example, the compiler while doing its thing, comes along to
    compile foo1. In it it finds foo2, but has not yet had any other references
    to foo2, and thus assumes the function to be external (i.e. will be in
    another file, and resolved at link time). It also at this time would assume
    foo2 takes integer arguments, and returns an integer.

    The compiler continues happily, but then comes across your function foo2,
    declared as static void foo2(void), which conflicts with its previous
    assumption, and so warns you.

    As other posters have said, the correction is to either declare a function
    prototype before any code:
    static void foo2(void); /* Note the semicolon */
    or changing the sequence in which your functions appear in the file.

    The former is preferred, as it also tells the compiler what arguments to
    expect, allowing it to issue other warnings when you try pass arguments of
    different types (or use its return type incorrectly).

    As others have also stated, making foo2 static means that if your project
    comprised of multiple files, functions in other files cannot reference this
    file's foo2. Think of a static function as akin to a private function to
    that file.

    Rich
     
    John Smith, Jun 30, 2003
    #3
  4. This is the prototype for foo2(). Without further notice, the compiler
    considers it like a non-static function .

    Note that prototypes belong to headers in most cases, and to c-files (out
    of a function) in rare occasions. Putting a prototype in a function in a
    non-sense.
    Now the compiler is disappointed because you lied to it. The function is
    static. So should have been the prototype.

    static void foo2(void);

    Note that a better layout avoids the use of separated prototypes for static
    functions. Just follow the state-of-art rule "Define before use".
    No surprise.
    Sounds that this foolish construct is not to be accepted by the language.
    Honsetly, I was not aware of that, but I /never/ put any prototype in a
    function.
    Sounds to be the canonic way.
    However, I recommend:

    /** stat_fn2.c **/

    #include <stdio.h>

    static void foo2(void)
    {
    printf("foo2\n");
    }

    static void foo1(void)
    {
    printf("foo1\n");
    foo2();
    }

    int main(void)
    {
    foo1();

    return 0;
    }
     
    Emmanuel Delahaye, Jun 30, 2003
    #4
  5. maxw_cc

    Chris Torek Guest

    It does not -- but hang on:
    It is, and:
    it is.
    This text is from the draft and will not match up with the final
    C99 standard. Footnote 21 says:

    21. A function declaration can contain the storage-class
    specifier static only if it is at file scope; see 6.5.1.

    and section 6.5.1 includes:

    6.5.1 Storage-class specifiers
    ...
    [#5] The declaration of an identifier for a function that
    has block scope shall have no explicit storage-class
    specifier other than extern.

    Why this prohibition? I have no idea -- but as I once said, if
    the standard says the behavior depends on the phase of the moon,
    the programmer should be prepared to look out the window as necessary.

    (In this case, the prohibition is harmless, because good style
    dictates that all function prototypes should be at file scope
    anyway. That is, while some functions can be prototyped at file
    scope, I recommend not doing so. If you make various easy-to-make
    mistakes in such a prototype, no diagnostic is required; if you
    move the prototype into a more appropriate place -- at file scope
    in the source file for "static"/internal-linkage functions, or into
    a header file that you include at file scope for external-linkage
    functions -- then these same errors *must* be diagnosed.)
     
    Chris Torek, Jul 1, 2003
    #5
  6. maxw_cc

    Dan Pop Guest

    ^^^^^^^
    ^^^^^

    I think you meant "at block scope".

    Dan
     
    Dan Pop, Jul 1, 2003
    #6
  7. maxw_cc

    Chris Torek Guest

    Er, yes.
     
    Chris Torek, Jul 1, 2003
    #7
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.