static keyword on none member functions - why???

Ah hello.

I would like some clarification on the use of "static" for a none member function, please.

From what I have read, it seems that the static keyword limits the function to be callable from within the .cpp file it is defined in.  But how is this different to when I don't have the static keyword: the function is literally only visible in the .cpp so how can it be callable from anywhere else?  I mean, if we have...
// .h
int GetInt();

// .cpp
int GetInt() 
	return 42;

Open in new window

...then clearly any file that includes the header can call GetInt().  So how can we possibly call GetInt() if we can't see its declaration via the header?

If I change the .cpp to have the static keyword, even though the function is "visible" via the header, I then get linker errors (unresolved external symbol "GetInt()") when I try and call it outside of the defining .cpp.  I guess this is so the .cpp can use the functions without having to bother about the order in which they are definedin the .cpp, whilst still preventing them from being callable outside that same .cpp.  Is this right?

Apart from this, the whole concept of static on a none member function hence seems totally redundant to me...
LVL 19
Who is Participating?
    int foo()  {...}

If foo is not declared in any .h file, then it can still be used in other .cpp files with this declaration:
    extern int foo();


    static  int foobar()  {...}

This foobar() cannot be used in other .cpp files even if it is declared in a .h file or by using an extern declaration.
a non-static function can be called from everywhere by only including the header file where the function was declared (or using a declaration of the function made in the calling source separately) .

the compiler is happy with that and when building the application the linker will bring the two modules together or give an error message when it can't find the called function.

mrwad99Author Commented:
So what exactly is the point of having the static keyword on a function that is not declared in a header file and defined in a single .cpp?  It does not add anything: we cannot attempt to call it from another module as the compiler will flag it as an error since it cannot "see" it, so we never get to the stage of the linker being unable to find it...
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

The "extern" in "extern int foo();" is optional for global functions.
"extern" is not optional for global variables.
A non-static non-member function is, in fact, visible in, and can be called by, functions in other files. We don't, by and large, do stuff like that anymore, because it would involve calling the function without the use of the prototype, which is there to make sure the arguments match. However, C was originally written like that, and so C++ supports it as well.

Thus the static keyword/storage class, which guarantees that the function can only be used in the file it is defined in.
There are distinctions between compiler errors and builder errors.

The compiler will give an error if a function is used without it being previously declared (or defined). If you have in a .h file:
    int foobar() ;
or in your .cpp file:
    int foobar() ;
then if you use it in a filename.cpp file, the compiler will not issue an error, since you have declared foobar().

In linux, if you wrote:
    g++ -c filename.cpp
then there should be no errors in compiling with calling foobar() since it is declared in one of the two ways.
evilrixSenior Software Engineer (Avast)Commented:
Hey mrwad99,

Long time no see (*waves*) :)

Although various answers have been given here none of them have actually explains the specific details of using static with a free functinn; so I will...

Symbols (functions, variables types etc) have what is called "linkage". This "linkage" basically defines whether the symbols that exist in your program can be seen by the linker (the stage after the compiler had finished) and, if so, under what scope.

Specifically, the C++ standard says the following about linkage...

"A name is said to have linkage when it might denote the same object, reference, function, type, template,
namespace or value as a name introduced by a declaration in another scope:

— When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.

— When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.

— When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes."

Normally, a free standing function will have external linkage but by defined it as static the linkage is changed to internal.

"A name having namespace scope has internal linkage if it is the name of an object, reference, function or function template that is explicitly declared static"

The use of static for this purpose, in C++, is now deprecated and should be avoided.

"The use of the static keyword is deprecated when declaring objects in a namespace scope (see annex D);
the unnamed-namespace provides a superior alternative.

D.2 static keyword - The use of the static keyword is deprecated when declaring objects in namespace scope."

Instead, you should use an anonymous namespace.

An unnamed-namespace-definition behaves as if it were replaced by

namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespace-body }

Open in new window

where all occurrences of unique in a translation unit are replaced by the same identifier and this identifier
differs from all other identifiers in the entire program.82)

namespace { int i; } // unique::i

void f() { i++; } // unique::i++

namespace A {
   namespace {
      int i; // A::unique::i
      int j; // A::unique::j
   void g() { i++; } // A::unique::i++

using namespace A;
void h() {
   i++; //error: unique::i or A::unique::i
   A::i++; // A::unique::i
   j++; // A::unique::j

Open in new window

mrwad99Author Commented:
Right, many thanks for helping with the clarification of this.


I had completely forgotten about the "extern" keyword, which is strange having used it so many times previously.  Ultimately, this is the answer to my question.


Good God, I have not heard your name since I first joined EE back in 2002, and you helped me understand dynamic memory allocation in C (http:Q_20417450.html)!  Good to see you are still on this site!  Thanks for participating here!


LTNS indeed!  I do hope you are well.  Thanks for this; the stuff on namespaces was useful.  The only thing I would like to say is where you talk about "unique": it took me a while to understand exactly what you meant there, so I googled it and came across (which could have been where your example code came from):  the use of italics in "unique" on that page highlight the fact that "unique" is a compiler generated value, which made the penny drop...hehe.
evilrixSenior Software Engineer (Avast)Commented:
>> I do hope you are well.  

Very well. I hope you are too - welcome back to the cool zone :)

>> where you talk about "unique": it took me a while to understand

Oooh, my apologies - this was a direct copy/paste from the C++ standard.... if I have cause to do so again I will be sure to add some additional verbiage to explain things. Thanks for the feedback.
Only Stroustrup, you, and one other EE expert can quickly interpret the C++ standard. So it is alway best to clarify when quoting from this standard.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.