Does the static keyword affect scope? - c++

In C89, does the static keyword affect scope?
My software lead told me:
"A variable marked static at the top of a file doesn't technically have global scope any longer. Static is a scope qualifier as well as a storage keyword. Scope is a
concept that covers visibility of symbols, though visibility is
automatically compiled to have storage duration intrinsically tied in
by almost all languages. By this I mean that you can't name a scope
that doesn't also define the storage duration in C/C++. Expression
scope is not user defined and in C/C++ covered by l-param and r-param
Block scope is fully lexical in C/C++ by user defined bodies Function
scope is fully lexical in C/C++ by user defined bodies and
declarations File scope does not technically exist in C/C++, as
globals and module scope take over depending upon lexicon Module scope
is keyword defined using static in C/C++, other scope lexicon change
the rules for access but the visibility remains module based Global
scope is the default in C/C++ when no other scope applies and is
lexically controlled by the extern keyword The issue is that static is
not JUST a scope qualifier as a keyword. It is a scope qualifier AND a
memory keyword."
I'm confused. I've always thought that static relates to the visibility between translation units and the storage duration of the variable. Both of which are unrelated to scope. Is this not the case? Is the static/scope relationship different in C++?

A variable marked static at the top of a file doesn't technically have global scope any longer.
"Global scope" is not a concept that exists in C. The proper term is file scope. In C++, a similar concept exists called the global namespace. It seems that overtime people combined the two terms.
Static is a scope qualifier as well as a storage keyword.
static is not a scope qualifier, it is a storage-class specifier. static can affect linkage and storage duration, but not scope.
Scope is a concept that covers visibility of symbols, though visibility is automatically compiled to have storage duration intrinsically tied in by
almost all languages.
Scope has nothing to do with visibility of symbols (in the linker sense). Linkage does (hence why it's called linkage). The second clause is gibberish.
By this I mean that you can't name a scope that doesn't also define the storage duration in C/C++.
This sentence also doesn't make sense. Consider a local static variable at block scope. It has static storage duration even though block scope defines automatic storage variables.
Expression scope is not user defined and in C/C++ covered by l-param and r-param
"Expression scope" makes no sense. "l-param" and "r-param are also meaningless words.
Skipping the part about "lexical" and "modules" because it makes zero sense.
The issue is that static is not JUST a scope qualifier as a keyword. It is a scope qualifier AND a memory keyword.
Again, static has nothing to do with scope or memory. Using this oversimplified explanation leaves out basically all other aspects of storage duration, scope and initialization so it just plain doesn't work.

Section 6.2.1 of the C11 standard defines what "scope" means:
For each different entity that an identifier designates, the identifier is visible (i.e., can be used) only within a region of program text called its scope. Different entities designated by the same identifier either have different scopes, or are in different name spaces. There are four kinds of scopes: function, file, block, and function prototype. (A function prototype is a declaration of a function that declares the types of its parameters.)
Section 3.1.2.1 of the C89/90 spec is almost identical:
An identifier is visible (i.e., can be used) only within a region
of program text called its scope . There are four kinds of scopes:
function, file, block, and function prototype. (A function prototype
is a declaration of a function that declares the types of its
parameters.)
So there is no such thing as global scope, at least as far as the C standard is concerned. An identifier defined outside of any function or block has file scope, and the presence or absence of static has no effect on that, only on the symbol's linkage, which is something completely different (but which your lead may be conflating or confusing with the term "scope").

Your informant is confused. static has no impact on scope whatsoever.
File scope is a misnomer because you can construct multifile translation units using #include directives or other hypothetical implementation-dependent facilities. Global scope is also a misnomer because a program can be made up of multiple translation units. Modules are still not part of the language.
static can affect linkage, but that is a different concept to scope.

The keyword static has several uses in C. For instance in a C source file at the top you might have:
#include <stdio.h>
// .. other includes and comments and stuff
int globallyVisibleInt = 0; // a variable that other compilation units can see
static int fileVisibleInt = 0; // a variable visible in the file from this point
The variable fileVisibleInt is created and initialized at the time the application loads however if you were to try to access it from some other compilation unit, you would get an error from the linker when trying to link.
You can also use static in a function to create a variable that will exist and maintain state.
int myFunc (int k)
{
static int mySavedInt = 0; // create and initialize a permanent int variable
if (k > 10) {
mySavedInt = k; // use the variable to save a value for the next time function is called
} else if (mySavedInt > 22) {
// do some stuff
}
}
The point at which a static variable is visible to the other source in the file is at the point where it appears in the source file and it's visibility is governed by the various scope rules. For instance a static defined in a function is only visible in that function or if a static is used in some other, more reduced scope such as an if or a for then it is a permanent variable that is only visible in that scope.
There are various phrases which are common usage but are not necessarily technically accurate or something you would find in the standards. For instance the phrase "global scope" means to me that the thing is visible outside of the compilation unit. By "module" I would assume function. For most day to day activities looseness of language works just fine.
In C++, static can be quite a bit different depending on whether you are using C++ constructs such as class and using static as a qualifier for methods and members or if you are using it the old C way.
See also:
File Scope and Global Scope: C & C++.
Why file scope static variables have to be zero-initialized?
Dr. Dobbs: Scope Regions in C++.

Related

Aren't non-const variable considered external by default?

Learning from this: By default, non-const variables declared outside of a block are assumed to be external. However, const variables declared outside of a block are assumed to be internal.
But if I write this inside MyTools.h:
#ifndef _TOOLSIPLUG_
#define _TOOLSIPLUG_
typedef struct {
double LN20;
} S;
S tool;
#endif // !_TOOLSIPLUG_
and I include MyTools.h 3 times (from 3 different .cpp) it says that tool is already defined (at linker phase). Only if I change in:
extern S tool;
works. Isn't external default?
The declaration S tool; at namespace scope, does declare an extern linkage variable. It also defines it. And that's the problem, since you do that in three different translation units: you're saying to the linker that you have accidentally named three different global variables, of the same type, the same.
One way to achieve the effect you seem to desire, a single global shared variable declared in the header, is to do this:
inline auto tool_instance()
-> S&
{
static S the_tool; // One single instance shared in all units.
return the_tool;
}
static S& tool = tool_instance();
The function-accessing-a-local-static is called a Meyers' singleton, after Scott Meyers.
In C++17 and later you can also just declare an inline variable.
Note that global variables are considered Evil™. Quoting Wikipedia on that issue:
” The use of global variables makes software harder to read and understand. Since any code anywhere in the program can change the value of the variable at any time, understanding the use of the variable may entail understanding a large portion of the program. Global variables make separating code into reusable libraries more difficult. They can lead to problems of naming because a global variable defined in one file may conflict with the same name used for a global variable in another file (thus causing linking to fail). A local variable of the same name can shield the global variable from access, again leading to harder-to-understand code. The setting of a global variable can create side effects that are hard to locate and predict. The use of global variables makes it more difficult to isolate units of code for purposes of unit testing; thus they can directly contribute to lowering the quality of the code.
Disclaimer: code not touched by compiler's hands.
There's a difference between a declaration and a definition. extern int i; is a declaration: it says that there's a variable named i whose type is int, and extern implies that it will be defined somewhere else. int i;, on the other hand, is a definition of the variable i. When you write a definition, it tells the compiler to create that variable. If you have definitions of the same variable in more than one source file, you've got multiple definitions, and the compiler (well, in practice, the linker) should complain. That's why putting the definition S tool; in the header creates problems: each source file that #include's that header ends up defining tool, and the compiler rightly complains.
The difference between a const and a not-const definition is, as you say, that const int i = 3; defines a variable named i that is local to the file being compiled. There's no problem having the same definition in more than one source file, because those guys all have internal linkage, that is, they aren't visible outside the source file. When you don't have the const, for example, with int i = 3;, that also defines a variable named i, but it has external linkage, that it, it's visible outside the source file, and having the same definition in multiple files gives you that error. (technically, it's definitions of the same name that lead to problems; int i = 3; and double i = 3.0; in two different source files still are duplicate definitions).
By default, non-const variables declared outside of a block are assumed to be external. However, const variables declared outside of a block are assumed to be internal.
That statement is still correct in your case.
In your MyTools.h, tool is external.
S tool; // define tool, external scope
In your cpp file, however, the extern keyword merely means that S is defined else where.
extern S tool; // declare tool

Why is a constant global object internally linked by default while any other global object is externally linked by default? [duplicate]

See subject. What were they thinking?
UPDATE: Changed from "static" to "internal linkage" to save confusion.
To give an example... Putting the following in a file:
const int var_a = 1;
int var_b = 1;
...and compiling with g++ -c test.cpp only exports var_b.
I believe you mean
Why does const imply internal linkage in C++
It's true that if you declare a const object at namespace scope, then it has internal linkage.
Appendix C (C++11, C.1.2) gives the rationale
Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage
Rationale: Because const objects can be used as compile-time values in C++, this feature urges programmers to provide explicit initializer values for each const. This feature allows the user to put const objects in header files that are included in many compilation units.
As litb said, const objects have internal linkage in C++. This is because they are intended to be used like this:
// a.cpp
const int BUFSIZE = 100;
char abuf[BUFSIZE];
// b.cpp
const int BUFSIZE = 256
int bbuf[BUFSIZE];
Const and static are orthogonal concepts in both C and C++.
The const keyword tells the compiler to disallow the variable from appearing as the lvalue of any expression - essentially making it read-only.
In C, the static keyword has several uses depending on what it is applied to. When applied to a variable of a function, it indicates that the variable is not stored in the local scope of a function, but is accessible across invocations of it. When applied to a global variable or function, it becomes accessible only to a particular file - in other words, it is accessible only within the compilation unit (unless declared extern).
In C++, the static keyword can be used within a class definition, to make a variable or functions shared across all instances of the class, rather than being local to each instance. Furthermore, a static class function in C++ can only access static variables of that class (or classes it has access to). Now, in C++ const does give members internal linkage to the compilation unit unless they are explicitly declared extern - this may be what you are referring it. This allows compile-time constants to be shared across unit through the use of header files. Keep in mind, though, that the members are not really static - rather the constant is compiled into each location where it is referenced.
In C & C++ the term static has multiple meanings (it can govern linkage and storage)
You'll have to read Stroustrup's D&E to appreciate his rationale - but when you declare a variable to be const at namespace scope it automatically has internal linkage - whereas in C you have to declare it static to force it to have internal linkage.
Of course in C++, the use of static to control linkage has been deprecated, anonymous namespaces can be used to simulate internal linkage in C++.
const variables in C++ were supposed to replace preprocessor constants - and since preprocessor constants are only visible in files that define them, similarly, const automatically makes the variable visible only in the file that defines it.
Those concepts are orthogonal and should not be thought as the same thing.
Constness is an access propriety : it tells only if your variable should be read-only (const) or write-read (non-const).
Staticity is a life-time (and technically memory localization) property : it tells if the variable will be global in the scope of a class (when in a class) or a translation unit (when used with a global variable defined in a cpp).
It doesn't, and the most obvious example is that if you have a const member variable (which is initialised by the constructor, of course), it is not shared by all objects of that class, but individual to each.
class A {
public:
A(int newx) : x(newx);
private
int x;
}
litb gives the best answer, above.
It doesn't. Writing the following:
const int i = 0;
doesn't make i static (in either C or C++).

Does compiler include global variables without static modifier in the global symbol table?

I've read in (Effective Objective-C 2.0) that static variables declared in implementation file (m.file) are local to the translation unit in which they are defined and these variables will not be exposed in the
global symbol table. But if a global varible in .m-file is declared without static it acts like a static. So is static used implicitly in such case or these are different matters?
Example:
//in the m.file
static int staticVariable;//100% static
int globalVariable;//is static ?
#implementation SomeClass {
//local ivars declaration
}
Placing variables is compiler dependent.
The compiler is allowed to place file static variables into the global variable segment, as long as the scoping rules are adhered to. Actually, the compiler can place the variables anywhere in read-write memory, again as long as the "as-if" rule is adhered to.
When defining variables at the file scope, the difference between using static and not, is that static hides the variable from other translation units. Otherwise they are treated the same.
Note: This applies to C++ since the OP has the C++ tag. I don't know if this also applies to Objective C since that is another language.

Can we consider global static variable as global variable

the question is can we call variable A "global variable"? From the one hand A is static global variable, so it is global by definition, from the other global variable must be available in every point of your program, not only in the current translation unit. Thanks.
#include<stdio.h>
static int A;
void main()
{
...
}
No, a static is not a global because it has internal linkeage. A copy will exist for each TU that defines it.
From the one hand A is static global variable, so it is global by definition
Why is it a static global variable? It's static, yes, but that's about it.
Global variables in C++ are those declared extern and defined only once, or contained as static members (which has a whole different meaning).
Your variable A has static storage and is defined at file scope, and it has internal linkage. The term "global variable" is only a colloquialism that doesn't capture all those nuances completely accurately. The variable is certainly global in the sense that it can be accessed from every scope, and its lifetime is from program start to program end, but because of its internal linkage, it cannot be accessed from outside the translation unit in which it is declared.
I don't think there's a specific, widespread terminology to indicate those "static globals"; the problem is that the standard never talks about "global variables" in general, but it distinguishes two orthogonal concepts:
the lifetime of the variable, which is the same for globals, "static globals" and static local variables; the standard calls all them "variables with static storage duration";
the visibility of these variables, which is different in all the cases; "globals" are variables defined at global namespace scope with external linkage; the "static globals" are defined at the same scope, but with internal linkage; finally, the static local variables have local scope.
Is it correct to call the "static globals" "globals"? As already said, the standard never defines "global variables", so it should be a matter of taste: they are defined at global namespace scope, but they are not accessible in other modules because of the fact that they have internal linkage.
Still, keep in mind that, generally, when talking about globals in C++ we refer to variables defined at global namespace scope with external linkage. So, all in all, I wouldn't call them globals, the only nonambiguous way to call them I see is "variables defined at global namespace scope with internal linkage".
As others have said, it depends on why you care about it being "global". In a large source file, a static variable can introduce hard-to-trace coupling between functions, much like a non-static function. The difference, of course, is that the static variable is confined to a single source file, but that's small comfort if you've got hundreds of functions in that source file that you have to wade through to figure out where that unexpected modification is coming from.
Think of it as a module variable, as it is visible to one module (intended here as "translation unit"), rather than visible to all modules.

file scope and static floats

I've run into an interesting problem in an AI project of mine. I'm trying to format some debug text and something strange is happening. Here's a block of code:
float ratio = 1.0f / TIME_MOD;
TIME_MOD is a static float, declared in a separate file. This value is modified based off of user input in another class (I have verified that the value is changed while still debugging within the scope of the "input" function), but whenever I try to divide by it in my outer loop I get the same number. (1 divided by the initial value of TIME_MOD).
Am I missing something regarding static variables and file scope?
I think there is some confusion with the word "static". We have a keyword static that does different things in different contexts and we use the word "static" to name one of three classes of "storage durations". In some contexts static does not control the storage duration of objects but only "linkage" which is probably the main reason for the confusion.
Storage durations
A storage duration is a property of an object.
The memory of an object with static storage duration is allocated once and once only. Initialization depends on the kind of object and where it is defined. Once it is initialized, it generally stays alive until the execution of main ends. Objects you declare and define at global/namespace scope always have a static storage duration.
Objects with automatic storage duration can only be defined inside a block in functions. Such an object is created when execution reaches the definition. This can happen multiple times (recursion) which creates multiple objects. When execution leaves the block the objects are automatically destroyed.
Dynamically allocated objects have a dynamic storage duration. In this case the user controls the life-time of the objects via new, new[], delete, delete[] etc.
Linkage
Internal vs external linkage is about visibility of names across translation units. If you declare something with external linkage you introduce a name that can be used in other translation units as well to refer to the same entity as long as those other TUs contain the proper declaration (usually contained in a header file). If you define something with internal linkage you can't access it from another translation unit by name. You can even define multiple entities with the same name (one per TU) as long as you have no more than one with external linkage.
The keyword "static"
The effect of static depends on the context:
If you declare or define an object at global/namespace scope it is always an object with "static storage duration". The use of the keyword static at global/namespace scope doesn't affect the storage duration at all. Instead, it affects linkage. It declares the entity -- which might be a function as well -- to have internal linkage. So, the storage class specifier has been "misused" to do something completely different: enforce internal linkage. It's sort of the opposite of extern in this context. In C++ you can achieve the same effect with an anonymous namespace. You are encouraged to prefer anonymous namespaces over static to "minimize confusion".
static at class scope can be used to declare objects with static storage duration in the scope of the class. There's only one such variable and not one for each object.
static at function scope can be used to declare objects with static storage duration that is lazily initialized
If you say "static variable" it's not clear what you mean exactly. Do you refer to the "static storage duration" or "internal linkage"?
If you want to share a "global" variable across translation units you have to declare it in a header file as an entity with external linkage and define it in exactly one translation unit. Note that the keyword static is not used:
// myheader.hpp
extern int k; // declaring an int variable with external linkage
// foo.cpp
#include "myheader.hpp"
int k; // defining an int variable with external linkage
// bar.cpp
#include "myheader.hpp"
int main() {
return k;
}
A static variable only exists within the current compilation unit. Remove the static from its definition and change it to "volatile" (Though this assumes you are using multiple threads, if not you needn't use volatile) and all should be fine.
Edit: By your answer here I am assuming you have some code as follows.
A.cpp:
static float TIME_MOD = <some value>;
B.CPP:
static float TIME_MOD = <some value>;
If you are doing this then TIME_MOD exists in 2 places and this is the source of your problems. You need to re-write the code more like this.
A.cpp:
float TIME_MOD = <some value>;
B.CPP (And C.CPP, D.CPP etc):
extern float TIME_MOD;
And then use TIME_MOD as usual. This tells the compiler that TIME_MOD is somewhere else and not to worry about not knowing what it contains. The linker will then go through and "link" this floating TIME_MOD definition to the correct definition.
Its also worth pointing out that it is probably work having the "extern float TIME_MOD;" in a header file somewhere and including it in any CPP files you need it in. Still keep the actual definition (ie the non extern'd definition) in one, and only one, file.
This would certainly explain the fact that I thought you were extern'ing a static (which i thought was impossible).
You could change the static variable to a #define, and set a member variable in a singleton equal to it. Modifications and accesses would apply to the singleton's member variable.
Static variables are linked internally. you can not access a static variable defined in some other source file.
The situation you are falling into may happen in case when you have defined the static variable TIME_MOD in some header file.Include the same header file in both the input and ratio source files, hence both files have a private copy of the variable TIME_MOD,
Now the input module changes the TIME_MOD value, but it modifies its own private copy so the value in ratio file remains unchanged and hence your behavior.
Now if that is the case you do not need a static TIME_MOD, and to resolve name conflicts you may like to use namespaces.
I guess you declared this variable in header file as: static float TIME_MOD;
And included this file in cpps. By doing this you effectively created separate instances of same named variable in each compilation unit.
You should change declaration to: extern float TIME_MOD;
And define variable in one of cpps: float TIME_MOD = 0;