static in front of function declared locally

M

maxw_cc

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
 
C

Chris Lowth

maxw_cc said:
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

"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
 
J

John Smith

maxw_cc said:
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

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
 
E

Emmanuel Delahaye

In 'comp.lang.c' said:
/** stat_fn.c **/

#include <stdio.h>

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

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.
printf("foo1\n");
foo2();
}

static void foo2(void)

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".
{
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'

No surprise.
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);

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.
printf("foo1\n");
foo2();
}

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

int main(void)
{
foo1();

return 0;
}

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

Sounds to be the canonic way.
/** 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...

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;
}
 
C

Chris Torek

Could you please quote the part where the standard forbids putting
prototypes within functions?

It does not -- but hang on:
Then my question is why is this wrong? Why the warning?
Isn't static a valid storage class for a function prototype?

It is, and:
Or is it only valid when the function is declared/defined at file
scope?

it is.
Could somebody please quote/point the part of the standard
that forbids this?

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.)
 
D

Dan Pop

In said:
(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
^^^^^

I think you meant "at block scope".

Dan
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top