linkage of static and inline functions

N

Nagrik

Dear Group,

The book of Bjarne Stroustrup in chapter 5.4.4 says the following

"The word static is one of the most overused words in C and C++. For
static data members it has both of the common meanings: static as in
"statically allocated" as opposed to on the stack or on the free store
and static as in "with restricted visibility" as opposed to with
external linkage. For member functions, static has the second
meaning."

In the same book in r.9.4 it says the following:

"Static members of global class have external linkage (r.3.3). The
declaration of a static data member in its class declaration is not a
definition.

AT r.3.3 it says:

"A name of file scope that is explicitly declared static is local to
its translation unit and can be uses as a name for other objects,
functions, and so on, in other translation units. Such names are said
to hae internal linkage. A name of file scope that is explicitly
declared inline is local to its translation unit..."

/** I am confused about the above mentioned statement (especially of
the phrase "A name of file scope". Can someone explain this) */

In the same section it says:

Static class members have external linkage.

1. By examining all three statements I am confused about the linkage
of static member functions as well as inline functions.

I have the following code

// File a.h
#include "stdafx.h"
#include "iostream.h"

class A {
public:
A() ;
static void someFn();
};

static void indFn();

//File a.cpp

#include "stdafx.h"
#include "a.h"
A::A() {cout << "Constuctor A"<< endl;}

void A::someFn() {cout << " print in static" << endl; }

static void indFn() {cout << " print in static ind" << endl; }

// File staticcheck.cpp

#include "stdafx.h"
#include "iostream.h"
#include "a.h"

int main(int argc, char* argv[])
{
A* a = new A;
a->someFn();
indFn();

return 0;
}

The file staticcheck.cpp only #includes a.h, however, the call to
function /* a->someFn() */ succeeds, although the definition of the
function is defined in a.cpp ( Contrary to internal linkage
directive). At the same time unless I declare and define indFn in a.h
the call to indFn() does not compile. If I declare the indFn in a.h
and define in a.cpp the code does not compile. Hence in this case it
is definitely Internal Linkage.

2. The inline functions also have internal linkage and it makes sense
to define them in each and every module. However, later discussions
give me the impression that compilers now support external linkage for
inline functions. If this is the case then it should obviate the need
to define inline function in every module, wherever it is used.

3. Lastly the static function belongs to the class and not to the
object. Hence, there is only one copy of the function available for
all threads to run. Does it mean if one thread is running the static
function, then that thread will hold a lock on that function and no
other thread can start running the code of that function unless the
other thread is done executing the static function.

4. What happens to local variables (not static variables) declared
inside static function. Do they retain their updated values across
multiple threads, or each thread gets to maintain independent values
for those variables.

Thanks

nagrik
 
A

Andrey Tarasevich

Nagrik said:
...
The book of Bjarne Stroustrup in chapter 5.4.4 says the following

"The word static is one of the most overused words in C and C++. For
static data members it has both of the common meanings: static as in
"statically allocated" as opposed to on the stack or on the free store
and static as in "with restricted visibility" as opposed to with
external linkage. For member functions, static has the second
meaning."

You must be used some very outdated version of the book. The meaning of
'static' for class members (both data member and member functions) is
completely different from anything in the above quote.
In the same book in r.9.4 it says the following:

"Static members of global class have external linkage (r.3.3). The
declaration of a static data member in its class declaration is not a
definition.

That is correct.
AT r.3.3 it says:

"A name of file scope that is explicitly declared static is local to
its translation unit and can be uses as a name for other objects,
functions, and so on, in other translation units. Such names are said
to hae internal linkage.

That is correct, but doesn't apply to class members.
A name of file scope that is explicitly
declared inline is local to its translation unit..."

I don't know what "local" stands for here. If it implies "internal
linkage" then it is incorrect. It used to be that way quite some time
ago, but not in the standardized C++. Your book must be heavily outdated.
/** I am confused about the above mentioned statement (especially of
the phrase "A name of file scope". Can someone explain this) */

Probably "a name declared in file scope".
In the same section it says:

Static class members have external linkage.

That's correct.
I have the following code
// File a.h
...
class A {
public:
A() ;
static void someFn();
};

static void indFn();

//File a.cpp
...
#include "a.h"
A::A() {cout << "Constuctor A"<< endl;}

void A::someFn() {cout << " print in static" << endl; }

static void indFn() {cout << " print in static ind" << endl; }

// File staticcheck.cpp
...
#include "a.h"

int main(int argc, char* argv[])
{
A* a = new A;
a->someFn();
indFn();

return 0;
}

The file staticcheck.cpp only #includes a.h, however, the call to
function /* a->someFn() */ succeeds, although the definition of the
function is defined in a.cpp ( Contrary to internal linkage
directive).

It should, since 'A::someFn' has external linkage.
At the same time unless I declare and define indFn in a.h
the call to indFn() does not compile. If I declare the indFn in a.h
and define in a.cpp the code does not compile. Hence in this case it
is definitely Internal Linkage.

As expected, since 'indFn' has internal linkage. If you declare and
define 'indFn' in 'a.h ' the code will compile, but you'll get a
different instance of 'indFn' in every translation unit.
2. The inline functions also have internal linkage and it makes sense
to define them in each and every module.

No. Inline functions have external linkage by default. Yet, they are
still required to be defined in every translation unit (where they are
used directly).
However, later discussions
give me the impression that compilers now support external linkage for
inline functions.

Yes, they do, since that's what the C++ standard says. However, the only
thing this basically means is that every inline function will have the
same address (result of the '&' operator) in every translation unit.
If this is the case then it should obviate the need
to define inline function in every module, wherever it is used.

Why? In order to simplify the actual inlining of the calls, the compiler
wants to see the definition in every translation unit. So, the language
requires it. This has absolutely nothing to do with linkage, external or
not. You have to keep in mind that the notion of "external linkage" in
C++ language is different from what is normally meant under this term in
some generic language-independent linker.
3. Lastly the static function belongs to the class and not to the
object. Hence, there is only one copy of the function available for
all threads to run. Does it mean if one thread is running the static
function, then that thread will hold a lock on that function and no
other thread can start running the code of that function unless the
other thread is done executing the static function.

C++ has no concept of thread, lock, etc. Yet, no. There's no need to
lock anything in this case.
4. What happens to local variables (not static variables) declared
inside static function. Do they retain their updated values across
multiple threads, or each thread gets to maintain independent values
for those variables.

Once again, see 3. Yet, no, automatic variables don't retain anything.
Neither between calls not between threads. Why would they?
 
N

nagrik

Nagrik said:
...
The book of Bjarne Stroustrup in chapter 5.4.4 says the following
"The word static is one of the most overused words in C and C++. For
static data members it has both of the common meanings: static as in
"statically allocated" as opposed to on the stack or on the free store
and static as in "with restricted visibility" as opposed to with
external linkage. For member functions, static has the second
meaning."

You must be used some very outdated version of the book. The meaning of
'static' for class members (both data member and member functions) is
completely different from anything in the above quote.
In the same book in r.9.4 it says the following:
"Static members of global class have external linkage (r.3.3). The
declaration of a static data member in its class declaration is not a
definition.

That is correct.
AT r.3.3 it says:
"A name of file scope that is explicitly declared static is local to
its translation unit and can be uses as a name for other objects,
functions, and so on, in other translation units. Such names are said
to hae internal linkage.

That is correct, but doesn't apply to class members.
A name of file scope that is explicitly
declared inline is local to its translation unit..."

I don't know what "local" stands for here. If it implies "internal
linkage" then it is incorrect. It used to be that way quite some time
ago, but not in the standardized C++. Your book must be heavily outdated.
/** I am confused about the above mentioned statement (especially of
the phrase "A name of file scope". Can someone explain this) */

Probably "a name declared in file scope".
In the same section it says:
Static class members have external linkage.

That's correct.




I have the following code
// File a.h
...
class A {
public:
A() ;
static void someFn();
};
static void indFn();
//File a.cpp
...
#include "a.h"
A::A() {cout << "Constuctor A"<< endl;}
void A::someFn() {cout << " print in static" << endl; }
static void indFn() {cout << " print in static ind" << endl; }
// File staticcheck.cpp
...
#include "a.h"
int main(int argc, char* argv[])
{
A* a = new A;
a->someFn();
indFn();
return 0;
}
The file staticcheck.cpp only #includes a.h, however, the call to
function /* a->someFn() */ succeeds, although the definition of the
function is defined in a.cpp ( Contrary to internal linkage
directive).

It should, since 'A::someFn' has external linkage.
At the same time unless I declare and define indFn in a.h
the call to indFn() does not compile. If I declare the indFn in a.h
and define in a.cpp the code does not compile. Hence in this case it
is definitely Internal Linkage.

As expected, since 'indFn' has internal linkage. If you declare and
define 'indFn' in 'a.h ' the code will compile, but you'll get a
different instance of 'indFn' in every translation unit.
2. The inline functions also have internal linkage and it makes sense
to define them in each and every module.

No. Inline functions have external linkage by default. Yet, they are
still required to be defined in every translation unit (where they are
used directly).
However, later discussions
give me the impression that compilers now support external linkage for
inline functions.

Yes, they do, since that's what the C++ standard says. However, the only
thing this basically means is that every inline function will have the
same address (result of the '&' operator) in every translation unit.
If this is the case then it should obviate the need
to define inline function in every module, wherever it is used.

Why? In order to simplify the actual inlining of the calls, the compiler
wants to see the definition in every translation unit. So, the language
requires it. This has absolutely nothing to do with linkage, external or
not. You have to keep in mind that the notion of "external linkage" in
C++ language is different from what is normally meant under this term in
some generic language-independent linker.
3. Lastly the static function belongs to the class and not to the
object. Hence, there is only one copy of the function available for
all threads to run. Does it mean if one thread is running the static
function, then that thread will hold a lock on that function and no
other thread can start running the code of that function unless the
other thread is done executing the static function.

C++ has no concept of thread, lock, etc. Yet, no. There's no need to
lock anything in this case.
4. What happens to local variables (not static variables) declared
inside static function. Do they retain their updated values across
multiple threads, or each thread gets to maintain independent values
for those variables.

Once again, see 3. Yet, no, automatic variables don't retain anything.
Neither between calls not between threads. Why would they?

--
Best regards,
Andrey Tarasevich- Hide quoted text -

- Show quoted text -

Andrey,

Only one clarification though.

From your reply I follow;

1. Static member functions inside a class have external linkage. And
will have single copy of
code.

2. Static global functinos (not belonging to any
class) have internal linkage and will have multiple
copies of codes with different addresses in an
application.

Thanks

nagrik
 
Y

Yakov Gerlovin

1. Not sure what is the question here.
The static member of a class has external linkage (9.4)
In your example it is A::someFn
the static function (which is a not a member of any class ) has an
internal linkage (3.3)

you have a forward declaration of 'indFn' in a.h and the definition of
'indFn' in a.cpp.
But since it is declared status it has internal linkage and visible
only inside the translation(or compilation) unit. (It is legal to
define 'indFn' also in staticcheck.cpp).

3. >the static function belongs to the class and not to the object.
Correct. Meaning, you can call the function on class, not on the
instance
Hence, there is only one copy of the function available for all threads to run.
Not sure what do you mean. The CODE segment is always shared for all
threads.
The static function, as any other function, can be called from several
threads simultaneously.

4. While threads share code segment, data segment and heap, each
thread has its own stack.
That's why local variable never require synchronization, only global/
static data can be accessed from several threads simultaneously.
What happens to local variables (not static variables) declared inside static function.
They are not preserved between calls (not from the same thread, nor
from different ones)

HTH
 
A

Andrey Tarasevich

nagrik said:
...
From your reply I follow;

1. Static member functions inside a class have external linkage. And
will have single copy of
code.
Yes.

2. Static global functinos (not belonging to any
class) have internal linkage
Yes.

and will have multiple
copies of codes with different addresses in an
application.

Well they _may_ have multiple copies. They _will_ have multiple copies
if you take explicit steps to create these copies. Like put the
function's definition into the header file and include it into several
translation units. Or manually copy the definition of the function into
several translation units.
 
J

James Kanze

The book of Bjarne Stroustrup in chapter 5.4.4 says the following

It would be interesting to know which version. Several things
suggest that you might be using an outdated version.
"The word static is one of the most overused words in C and
C++. For static data members it has both of the common
meanings: static as in "statically allocated" as opposed to on
the stack or on the free store and static as in "with
restricted visibility" as opposed to with external linkage.
For member functions, static has the second meaning."

Note here that he's trying to explain the situation in very
everyday language (and doing a pretty good job of it, IMHO).
This is not the language of the standard.

The restricted visibility he's talking about here is the class;
class members are not visible outside the scope of the class. A
static class member is exactly like a free function, except that
it has restricted visibility, and it has access to private
members of the class.
In the same book in r.9.4 it says the following:
"Static members of global class have external linkage (r.3.3).
The declaration of a static data member in its class
declaration is not a definition.

This is more formal, and corresponds to the actual language in
the standard.
AT r.3.3 it says:
"A name of file scope that is explicitly declared static is local to
its translation unit and can be uses as a name for other objects,
functions, and so on, in other translation units. Such names are said
to hae internal linkage. A name of file scope that is explicitly
declared inline is local to its translation unit..."

And this makes me think you're using an outdated copy: "file
scope" was removed from C++ when namespaces were introduced.
Replace "file scope" with "namespace scope" in the above.
/** I am confused about the above mentioned statement
(especially of the phrase "A name of file scope". Can
someone explain this) */

There are a number of different types of scopes in C++. The
most important ones are namespace scope, block (or local) scope
and class scope. If the name is declared outside of any
function or class, it has namespace scope (and in an earlier
time, before namespaces, it had file scope).

By default, a name declared in namespace scope has external
linkage---the same name, declared in the same scope, in a
different translation unit, refers to the same entity. If the
declaration contains the keyword static, then the name has
internal linkage: other declarations of the name in the same
scope and in the same translation unit refer to the same entity,
but declarations in other translation units don't.
In the same section it says:
Static class members have external linkage.

Yes. In fact, all class members have external linkage.
1. By examining all three statements I am confused about the
linkage of static member functions as well as inline
functions.
I have the following code
// File a.h
#include "stdafx.h"
#include "iostream.h"
class A {
public:
A() ;
static void someFn();
};
static void indFn();

Attention. This function has internal linkage. It is very,
very rare to declare anything with internal linkage in a header.
(The one exception might be constants.)
//File a.cpp
#include "stdafx.h"
#include "a.h"
A::A() {cout << "Constuctor A"<< endl;}
void A::someFn() {cout << " print in static" << endl; }
static void indFn() {cout << " print in static ind" << endl; }
// File staticcheck.cpp
#include "stdafx.h"
#include "iostream.h"
#include "a.h"
int main(int argc, char* argv[])
{
A* a = new A;
a->someFn();
indFn();

And this shouldn't compile, because you don't have a definition
of indFn() (the one in this translation unit, which is not the
one in a.cpp) anywhere.
return 0;
}
The file staticcheck.cpp only #includes a.h, however, the call to
function /* a->someFn() */ succeeds, although the definition of the
function is defined in a.cpp ( Contrary to internal linkage
directive).

Class members never have internal linkage. You actually quoted
a statement which said this for static class members. Class
members always have external linkage.
At the same time unless I declare and define indFn in a.h
the call to indFn() does not compile.

That's because indFn does have internal linkage.
If I declare the indFn in a.h and define in a.cpp the code
does not compile. Hence in this case it is definitely
Internal Linkage.
2. The inline functions also have internal linkage and it
makes sense to define them in each and every module. However,
later discussions give me the impression that compilers now
support external linkage for inline functions. If this is the
case then it should obviate the need to define inline function
in every module, wherever it is used.

Inline functions implicitly had internal linkage for the longest
time (and many compilers didn't support external linkage for
them). I suspect that this was never desired, but was only due
to implementation constraints. The techniques necessary to
implement templates also permitted giving inline functions
external linkage, and the standard adopted this. Today, inline
functions behave exactly like any other function in this
respect (and all reasonably recent compilers support this).

There is a second issue, however. There is a rule in C++ that
says that a function, a reference or an object with external
linkage shall have exactly one definition in the entire program.
Defining such an entity in more than one translation unit
results in undefined behavior. There are two major exceptions,
however: inline functions, and non-exported template entities.
In these two cases, the standard requires the entity to be
defined in every translation unit where it is used; it also
requires that all of the definitions be indentical. This has
nothing to do with the "linkage", however.

If you want to see the actual linkage, try taking the address of
the function. If you define something like:

inline void someFunc() { }

in a header, all &someFunc should compare equal, regardless of
the translation unit. Similarly, if someFunc contains a static
variable:

inline int* someFunc() { static int i ; return &i ; }

the return value must be the same in all translation units.

If instead you wrote:

inline static int* someFunc() { static int i ; return &i ; }

Then the return value and the address of the function must be
different in every translation unit.
3. Lastly the static function belongs to the class and not to the
object. Hence, there is only one copy of the function available for
all threads to run. Does it mean if one thread is running the static
function, then that thread will hold a lock on that function and no
other thread can start running the code of that function unless the
other thread is done executing the static function.

Functions don't have locks. And the current C++ standard
assumes a single threaded execution model. In practice, of
course, in a multithreaded environment, there's nothing to
prevent multiple threads from entering the same function at the
same time. Regardless of the linkage or scope of the function.
4. What happens to local variables (not static variables) declared
inside static function.

The same as for a non-member function. Each time the function
is called, a new set of local variables is allocated.
Do they retain their updated values across multiple threads,

What do you mean by that? A function is called from a specific
thread, and the thread that invocation is executing in doesn't
change.
or each thread gets to maintain independent values for those
variables.

Nothing to do with threads. Each invocation of a function has
its own instance of the local variables.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top