Why STATIC keyword is needed?

B

Bryan Parkoff

I have noticed that C programmers put static keyword beside global
variable and global functions in C source codes. I believe that it is not
necessary and it is not the practice in C++. Static keyword is useful
inside struct, class, and function only unless you want to force local
variable to be global variable so static is used.
Do you have idea why most programmers do this?

Bryan Parkoff
 
M

Mikhail Polatov

Bryan Parkoff said:
I have noticed that C programmers put static keyword beside global
variable and global functions in C source codes. I believe that it is not
necessary and it is not the practice in C++. Static keyword is useful
inside struct, class, and function only unless you want to force local
variable to be global variable so static is used.
Do you have idea why most programmers do this?

To enforce internal linkage. The same thing can be achieved by putting
globals into unnamed namespace.
 
B

Bryan Parkoff

Mikhail Polatov said:
To enforce internal linkage. The same thing can be achieved by putting
globals into unnamed namespace.

Mikhail,

I have read a book what it explained internal linkage. I am not sure I
understand what internal linkage means. I always place global variables and
global variables inside namespace in C++ unlike C. Is it true that I don't
need to use static keyword beside global variables and global variables if
they are always in global scope.
Please explain what is the difference between internal linkage and
external linkage. Thanks...

Bryan Parkoff
 
M

Mikhail Polatov

Bryan Parkoff said:
Mikhail,

I have read a book what it explained internal linkage. I am not sure I
understand what internal linkage means. I always place global variables and
global variables inside namespace in C++ unlike C. Is it true that I don't
need to use static keyword beside global variables and global variables if
they are always in global scope.
Please explain what is the difference between internal linkage and
external linkage. Thanks...

3.5.2 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.
 
B

Bryan Parkoff

Mikhail Polatov said:
3.5.2 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.

Mikhail,

Thank you for explaining the difference between internal linkage and
external linkage. I still don't understand your comment. I think that
external linkage means to call variables or functions from first file to
another second file. Internal linkage means to bind all local variables and
local functions inside struct, class, or namespace. Also, another meaning
is to hold global variables and global functions inside one file which they
are inaccessible to other files.

For Example:

// First_File.h
#ifndef FIRST_FILE.H
#define FIRST_FILE.H

extern int Obj1;
extern int Obj2;
extern int Obj3;

extern void Read_Obj(void);

#endif

// First_File.cpp
#include "First_File.h"
#include <stdio.h>

int Obj1 = 0;
int Obj2 = 0;
int Obj3 = 0;

void Read_Obj(void)
{
for (int a = 0; a < 10; ++a)
{
Obj1 += 1;
Obj2 += 2;
Obj3 += 3;
}

printf("Obj1: %d\nObj2: %d\nObj3: %d\n", Obj1, Obj2, Obj3);
}

// Second_File.cpp
#include "First_File.h"

int main(void)
{
Read_Obj();

return 0;
}

My example source code above is external linkage. Please give me your
example source which it is the internal linkage including static. I always
add namespace each header files and source code files to prevent overwritten
existing global variables according to my choice, but I can use struct or
class if I want on depend of my design.
The problem is that Read_Obj() function can't be forced inline. It is
not the C++ Compiler's decision to grant or deny __forceinline because
Read_Obj() function has external linkage. It creates two object files such
as *.obj. It is impossible to copy Read_Obj() function from first *.obj to
second *.obj which it pastes into main() function.
If Read_Obj() function is placed in Second_File.cpp rather than
First_File.cpp, __forceinline will work while C++ Compiler can always grant
or deny __forceinline because Read_Obj() function has internal linkage.
I used three different C++ Compiler such as Microsoft Visual C++, Intel
C++ Compiler, and GCC Compiler, but their results are always the same.
Is my concept explanation correct?

Bryan Parkoff
 
M

Mikhail Polatov

Bryan Parkoff said:
Mikhail,

Thank you for explaining the difference between internal linkage and
external linkage. I still don't understand your comment. I think that
external linkage means to call variables or functions from first file to
another second file. Internal linkage means to bind all local variables and
local functions inside struct, class, or namespace. Also, another meaning
is to hold global variables and global functions inside one file which they
are inaccessible to other files.

For Example:

// First_File.h
#ifndef FIRST_FILE.H
#define FIRST_FILE.H

extern int Obj1;
extern int Obj2;
extern int Obj3;

External linkage, extern modifier.
extern void Read_Obj(void);

The same.
#endif

// First_File.cpp
#include "First_File.h"
#include <stdio.h>

int Obj1 = 0;
int Obj2 = 0;
int Obj3 = 0;

External linkage by default.
void Read_Obj(void)
{
for (int a = 0; a < 10; ++a)
{
Obj1 += 1;
Obj2 += 2;
Obj3 += 3;
}

printf("Obj1: %d\nObj2: %d\nObj3: %d\n", Obj1, Obj2, Obj3);
}

// Second_File.cpp
#include "First_File.h"

int main(void)
{
Read_Obj();

return 0;
}

My example source code above is external linkage. Please give me
your example source which it is the internal linkage including
static. I always add namespace each header files and source code
files to prevent overwritten existing global variables according to
my choice, but I can use struct or class if I want on depend of my
design.


// internal linkage

static int obj1 = 0; // way 1: use static modifier
int const obj2 = 0; // way 2: use const without extern modifier

static void foo();

namespace {

int obj3 = 0; // way 3: use unnamed namespace

void foo2();

}
The problem is that Read_Obj() function can't be forced inline. It
is not the C++ Compiler's decision to grant or deny __forceinline
because Read_Obj() function has external linkage. It creates two
object files such as *.obj.

The __forceinline keyword is MSVC specific compiler extension. It has
the same semantics as inline has, but while the latter is just a hint
to the compiler, the former forces the compiler to do inlining (under
some conditions).

IHMO, in this example the function Read_Obj is not a good candidate
for inlining anyway.
It is impossible to copy Read_Obj() function from first *.obj to
second *.obj which it pastes into main() function.

And what for? Those object files may end up in different
programs/libraries. Don't forget about ODR (One Definition Rule).
If Read_Obj() function is placed in Second_File.cpp rather than
First_File.cpp, __forceinline will work while C++ Compiler can
always grant or deny __forceinline because Read_Obj() function has
internal linkage.

The compiler does compile translation units one at a time, and it
doesn't resolve any references between translation units, but a linker
does. And it's too late for the linker to any inlining since all code
have already been generated.

And as mentioned above, __forceinline does force inlining without any
cost/performance analysis, but it makes sense for functions with
internal linkage only.
 
B

Bryan Parkoff

Mikhail Polatov said:
External linkage, extern modifier.


The same.


External linkage by default.



// internal linkage

static int obj1 = 0; // way 1: use static modifier
int const obj2 = 0; // way 2: use const without extern modifier

static void foo();

namespace {

int obj3 = 0; // way 3: use unnamed namespace

void foo2();

}


The __forceinline keyword is MSVC specific compiler extension. It has
the same semantics as inline has, but while the latter is just a hint
to the compiler, the former forces the compiler to do inlining (under
some conditions).

IHMO, in this example the function Read_Obj is not a good candidate
for inlining anyway.


And what for? Those object files may end up in different
programs/libraries. Don't forget about ODR (One Definition Rule).


The compiler does compile translation units one at a time, and it
doesn't resolve any references between translation units, but a linker
does. And it's too late for the linker to any inlining since all code
have already been generated.

And as mentioned above, __forceinline does force inlining without any
cost/performance analysis, but it makes sense for functions with
internal linkage only.

Mikhail,

Thank you very much for explaining. I now understand clear. Do you
think that internal linkage with inline / without inline functions can gain
better performance than external linkage because it reduces too many needed
functions. Place static on global variables and global functions help to
hide from the public so they are always inaccessible like class' private
keyword.
I would use static keyword to place global variables and global
functions inside namespace rather than global scope so my large project
always looks neat with no mess.
Thanks again...

Bryan Parkoff
 
M

Marc Mutz

Mikhail Polatov wrote:
To enforce internal linkage. The same thing can be
achieved by putting globals into unnamed namespace.
<snip>

IIRC, anonymous namespace objects have external linkage,
just like with any other namespace, including the global
one.

namespace {
extern int e_count; // explicit external
int count; // implicit external
static int s_count; // internal

extern const int ec_count; // external
const int c_count; // implicit internal
static const int sc_count; // explicit internal
}

I fell into the same trap when I learned that the standard
deprecates file-statics, and that one should use
anonymous namespaces instead. Until a team member
helpfully pointed out to me that the number of external
symbols had grown considerably since I started removing
deprecated stuff from the project :)

Marc
 
M

Mikhail Polatov

Marc Mutz said:
Mikhail Polatov wrote:

<snip>

IIRC, anonymous namespace objects have external linkage,
just like with any other namespace, including the global
one.

namespace {
extern int e_count; // explicit external
int count; // implicit external
static int s_count; // internal

extern const int ec_count; // external
const int c_count; // implicit internal
static const int sc_count; // explicit internal
}

I fell into the same trap when I learned that the standard
deprecates file-statics, and that one should use
anonymous namespaces instead. Until a team member
helpfully pointed out to me that the number of external
symbols had grown considerably since I started removing
deprecated stuff from the project :)

According to STD 3.5.4:
A name having namespace scope has external linkage if it is the name
of:
<snip>
- a namespace (7.3), unless it is declared within an unnamed namespace

But extern modifier overrides any implicit internal linkage.
 
M

Marc Mutz

Mikhail Polatov wrote:
According to STD 3.5.4:
A name having namespace scope has external linkage if it
is the name of:
<snip>
- a namespace (7.3), unless it is declared within an
unnamed namespace

But extern modifier overrides any implicit internal
linkage.

And your point is...?
3 A name having namespace scope
(_basic.scope.namespace_) has internal linkage if it is
the name of

--an object, reference, function or function template
that is explicitly declared static or,

Ie. in
namespace { static int i; static void f(); }
both 'i' and 'f' have internal linkage.
--an object or reference that is explicitly declared
const and neither explicitly declared extern nor
previously declared to have external linkage; or

Ie. in
namespace { const int i; }
'i' has internal linkage
--the name of a data member of an anonymous union.

4 A name having namespace scope has external linkage if
it is the name of

--an object or reference, unless it has internal
linkage; or

Ie. in
namespace { int i; }
'i' has external linkage
--a function, unless it has internal linkage; or

Ie. in
namespace { void f(); }
'f' has external linkage
--a named class (_class_), or an unnamed class
defined in a typedef declaration in which the class
has the typedef name for linkage purposes
(_dcl.typedef_); or
--a namespace (_basic.namespace_), unless it is
declared within an unnamed namespace.

Isn't that exactly what I summarised in my previous post?

Marc
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top