While reading some questions and answers in stackoverflow I come across this question
I tried to understand it but the answers were really hard to understand especially the terms like
static storage duration
the expression cannot be evaluated during translation phase
etc...
Besides, I thought that constants are always constants (This is what I learnt from school)
Please can someone makes it a little bit easy to understand ?
In C (unlike C++), an arithmetic expression is a "constant expression" only if every value in the expression is a numeric constant or the name of an enumeration value. That is, although you might have declared a variable to be a static const int, you still cannot use that (constant) variable in a constant arithmetic expression.
Note that "constant expression" is a phrase defined by the formal standard which defines the C language. There are other expressions which are intuitively constant, but they are not included in the formal definition.
A variable with "static storage duration" is simply a variable which exists throughout the execution of the program. Most such variables are global variables (i.e. not part of any function, not even main), but in C and C++ you can have a static variable inside the scope of a function. Such a variable is initialized only once, and only a single instance of it exists regardless of how many times the function is called.
Global variables, and other variables with static storage duration, can only be initialized to a constant expression as per the above definition. This is the case whether or not they are const variables. The issue is simply that the variables have static storage duration, which means that they must be initialized before the program executes. (A variable with static storage duration exists throughout the execution of the program, so if it is initialized -- that is, given an initial value, as opposed to being assigned a value during the program's execution -- the initialization must occur before the program executes.)
In C++, a variable declared static const is considered a constant value, so it can appear in constant expressions. In C, however, that is not the case, so a C compiler does not need to track the initial value of static const variables.
There are two almost completely unrelated concepts here:
"constant expressions" are code that can be run at compile time.
4+5 is a constant expression.
const A=4; makes A into a constant expression sometimes in certain contexsts, since it's const and initialized from a constant expression 4. (This only applies to C++, not to C)
B=A; A may itself a constant expression, but B is a variable, and may not itself be in constant expressions.
const variables are variables that a function (or structure) promises not to change, though other things may change that same variable.
In C, a const-qualified variable is not the same thing as a constant. The integer literals 50 and 100 are constant expressions; their values are known at compile time (that is, they can be evaluated during the translation phase, meaning when the compiler is translating the source code into machine code). However, the variables a, c, and d won't have their values set until run time1; this means they cannot be used in a context where a compile-time constant is required2 (they cannot be evaluated during the translation phase). All the const qualifier does is tell the compiler to reject any code that attempts to modify those variables after they've been initialized.
The problem in the linked question is that endX and endY are being declared at file scope, outside of any function. Because of this, the variables have static storage duration, meaning storage for them is set aside when the program is first loaded into memory, before main executes, and held until the program terminates3. Since they are loaded before main executes, they cannot be initialized with an expression whose value won't be known until after main executes.
1. I know at least one version of gcc will build the executable file such that any static const-qualified variables will have their initial value set when the program is loaded; however, they are still treated as though they aren't initialized until after main starts.
2. C++ is different in this regard; static const-qualified variables are considered to be compile-time constants in that language.
3. Variables declared within a function or block with the static keyword also have static storage duration, meaning they exist for the lifetime of the program, but are not accessible outside of that function or block.
you are confused by const and constant.
const decorator decorates a variable and it has to have a memory location.(but not necessary true with register.) it mainly shows to human and compiler that the value of this variable is not supposed to be changed.
constant is an expression which compiler knows the meaning of.
so if you do:
const float PI = 3.14;
in file scope, it will allocate memory and having static storage duration, which essentially has the same life time as the process.
but if you do:
#define PI2 (3.14)
that's a different story, since no memory will contain this info.
so if you write:
float foo1 = 2 * PI;
float foo2 = 2 * PI2;
you can be sure that foo2 will be directly assigned to 6.28 after compilation, while whether foo1 is so or not is implementation defined, since it really depends on optimization skill called constant substitution.
Related
int a = 5;
int b = a; //error, a is not a constant expression
int main(void)
{
static int c = a; //error, a is not a constant expression
int d = a; //okay, a don't have to be a constant expression
return 0;
}
I don't understand what happens when a C compiler handles those variable declarations.
Why was C designed to be unable to handle int b = a?
The specific rule that applies here is C 2018 6.7.9 4:
All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.
The primary reason for this arises from the way that C is typically implemented, with a compiler generating object modules (which are later linked into executables and run). In such a C implementation, initializing an object with static storage duration requires the compiler to know the initial value, whereas initializing an object with automatic storage duration does not require the compiler to know the initial value.
This is because, to initialize an object with static storage duration, the compiler must put the initial value into the object module being generated. To initialize an object with automatic storage duration, the compiler merely needs to generate instructions to get or calculate the initial value and store it in the object.
When int a = 5; and int b = a; appear outside of any function, a and b have static storage duration. At this point, the compiler could, in theory, see that a was initialized with the value five, so it has that value when used in int b = a;. However, there are some issues with this:
It requires the compiler to maintain knowledge about objects it is not currently required to maintain.
It can only be done in certain circumstances, as when the initializer for b uses only objects that have been initialized earlier in the same translation unit. Extending the language to require the compiler to support this would require more complicated rules.
It requires extending the language semantics to specify what values objects have before the program is executed at all.
Another possibility would be that, to make initializations like int b = a; work, the compiler does it by generating instructions to be executed when the program starts, possibly immediately before main is called. This adds complications, including:
If int b = a; appears in a translation unit other than the one containing main, how is the code necessary to initialize b inserted in main or in the program start-up code?
When there are multiple such initializations, some of which may depend on each other, how do you ensure they are executed in the desired order?
These problems could be solved, in theory, but C is intended to be a “simple” language.
This happens because variables declared outside any function (at file scope) or variables declared as static both get static storage duration. Such variables are initialized before main() is even called. And that early on in the execution, values that aren't pure constant expressions might not yet be available.
RAM-based hosted systems like PC might even initialize such variables in one go, at the point where the executable is copied from the hard-drive to RAM, which gives very fast initialization. Which wouldn't be possible if you did something like static x = func(); because then you definitely have to execute func() before setting x.
There's also the issue of static initialisation order. Suppose a and b were declared in separate files, which should get initialized first, a or b?
C++ unlike C has decided to allow more complex forms of initialization and as a result, C++ has very complex initialization rules. And also it is a very common C++ bug to write code depending on the order of static initialization. There are valid arguments for/against both the C and the C++ way.
I have following piece of code:
#include <stdio.h>
int f1()
{
static int s=10;
printf("s=%d\n",s++);
}
int main()
{
f1();
f1();
return 0;
}
The output is:
s=10
s=11
Why is the line static int s=10 ignored at the second time, when f1 is called?
That is no assignment, but an initializer. Local static variables are only initialized once at program startup like global variables. They keep their last assigned value even between invocations of the function. Thus after your first call, it retains the value 11. In fact, they are like file-scope static variables, with their name only known in the scope of the block they are declared (but you can pass them by pointer).
Drawback is they only exist once. If you invoke the same function from multiple threads, they all share the same variable.
Try a third call: you will get 12.
Note: the initializer must be a constant expression. Try static int s = 10, t = s + 5; and read the compiler error message.
Initialization of a static variable is one-time (with the time of initialization guaranteed to occur before the first call, which could occur at compile time or at run time; compiler dependent). That's the main reason to use them.
The static variables are initialized only once, conceptually even before application has started.
From C11 (N1570) §5.1.2/p1 Execution environments:
All objects with static storage duration shall be initialized (set to
their initial values) before program startup.
along with §6.2.4/p3 Storage durations of objects:
Its lifetime is the entire execution of the program and its stored
value is initialized only once, prior to program startup.
As others have said, a static variable at function scope is initialized only once. So the assignment doesn't happen on subsequent calls to the function.
Unlike other local variables, a static local is not defined on the stack but in the data segment, probably in the same location as global variables. Globals are also initialized at application startup (they have to, since they don't live inside of a function and therefore can't be executable code), so conceptually you can think of a static variable as a global variable with limited visibility.
From the C89 Standard HTML version at 3.1.2.4 Storage durations of objects it specifies:
An object declared with external or internal linkage, or with the storage-class specifier static has static storage duration. For such an object, storage is reserved and its stored value is initialized only once, prior to program startup. The object exists and retains its last-stored value throughout the execution of the entire program
(The emphasis is mine)
So it says that everytime you use the static qualifier, that variable preserves its value across multiple function calls.
Local variables that are not static are initialized everytime you call the function that delcares them, so they do not preserve their value across function calls.
Hope this helped!
I am a newbie to C. I was reading the book by Kernighan & Ritchie and found that external variables must be initialized only with constant expressions. Why is it so? Can you explain me what happens internally? When are they initialized? Why can't we initialize an external variable using those defined before it?
According to C99 Standard: Section 6.7.8:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
And external variables have static storage duration, so it must be initialized by constant expressions or string literals.
Here is a link maybe give you better explaination.
http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
They have a explaination I quote below:
extern int var = 0;
int main(void)
{
var = 10;
return 0;
}
Analysis: Guess this program will work? Well, here comes another
surprise from C standards. They say that..if a variable is only
declared and an initializer is also provided with that declaration,
then the memory for that variable will be allocated i.e. that variable
will be considered as defined. Therefore, as per the C standard, this
program will compile successfully and work.
Hope this could help.
Any object with static storage duration such as variables declared outside of a function or variables inside a function declared as static can only be initialized with constant values.
The basic reason for this is that executable statements can't be placed outside of a function.
If such objects are not explicitly initialized then they are initialized to zero for arithmetic types or the null pointer for pointer types.
The common implementation is for values assigned to objects with static storage duration to be written directly into the executable image as data and loaded with the program image.
I know when a program is run, the main() function is executed first. But when does the initialization of global variables declared outside the main() happens? I mean if I declare a variable like this:
unsigned long current_time = millis();
void main() {
while () {
//some code using the current_time global variable
}
}
Here, the exact time when the global variable initializes is important. Please tell what happens in this context.
Since you didn't define the language you're talking about, I assumed it to be C++.
In computer programming, a global variable is a variable that is accessible in every scope (unless shadowed). Interaction mechanisms with global variables are called global environment (see also global state) mechanisms. The global environment paradigm is contrasted with the local environment paradigm, where all variables are local with no shared memory (and therefore all interactions can be reconducted to message passing). Wikipedia.
In principle, a variable defined outside any function (that is, global, namespace, and class static variables) is initialized before main() is invoked. Such nonlocal variables in a translation unit are initialized in their declaration order (§10.4.9). If such a variable has no explicit initializer, it is by default initialized to the default for its type (§10.4.2). The default initializer value for built-in types and enumerations is 0. [...] There is no guaranteed order of initialization of global variables in different translation units. Consequently, it is unwise to create order dependencies between initializers of global variables in different compilation units. In addition, it is not possible to catch an exception thrown by the initializer of a global variable (§14.7). It is generally best to minimize the use of global variables and in particular to limit the use of global variables requiring complicated initialization. See.
(Quick answer: The C standard doesn't support this kind of initialization; you'll have to consult your compiler's documentation.)
Now that we know the language is C, we can see what the standard has to say about it.
C99 6.7.8 paragraph 4:
All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.
And the new 2011 standard (at least the draft I has) says:
All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.
So initializing a static object (e.g., a global such as your current_time) with a function call is a constraint violation. A compiler can reject it, or it can accept it with a warning and do whatever it likes if it provides an language extension.
The C standard doesn't say when the initialization occurs, because it doesn't permit that kind of initialization. Basically none of your code can execute before the main() function starts executing.
Apparently your compiler permits this as an extension (assuming you've actually compiled this code). You'll have to consult your compiler's documentation to find out what the semantics are.
(Normally main is declared as int main(void) or int main(int argc, char *argv[]) or equivalent, or in some implementation-defined manner. In many cases void main() indicates a programmer who's learned C from a poorly written book, of which there are far too many. But this applies only to hosted implementations. Freestanding implementations, typically for embedded systems, can define the program's entry point any way they like. Since you're targeting the Arduino, you're probably using a freestanding implementation, and you should declare main() however the compiler's documentation tells you to.)
I have used a static global variable and a static volatile variable in file scope,
both are updated by an ISR and a main loop and main loop checks the value of the variable. here during optimization neither the global variable nor the volatile variable are optimized. So instead of using a volatile variable a global variable solves the problem.
So is it good to use global variable instead of volatile?
Any specific reason to use static volatile??
Any example program would be appreciable.
Thanks in advance..
First let me mention that a static global variable, is the same as a global variable, except that you are limiting the variable to the scope of the file. I.e. you can't use this global variable in other files via the extern keyword.
So you can reduce your question to global variables vs volatile variables.
Now onto volatile:
Like const, volatile is a type modifier.
The volatile keyword was created to prevent compiler optimizations that may make code incorrect, specifically when there are asynchronous events.
Objects declared as volatile may not be used in certain optimizations.
The system always reads the current true value of a volatile object at the point it is used, even if a previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment. That means there is no caching of a volatile variable into a CPU register.
Dr. Jobb's has a great article on volatile.
Here is an example from the Dr. Jobb's article:
class Gadget
{
public:
void Wait()
{
while (!flag_)
{
Sleep(1000); // sleeps for 1000 milliseconds
}
}
void Wakeup()
{
flag_ = true;
}
...
private:
bool flag_;
};
If the compiler sees that Sleep() is an external call, it will assume that Sleep() cannot possibly change the variable flag_'s value. So the compiler may store the value of flag_ in a register. And in that case, it will never change. But if another thread calls wakeup, the first thread is still reading from the CPU's register. Wait() will never wake-up.
So why not just never cache variables into registers and avoid the problem completely?
It turns out that this optimization can really save you a lot of time overall. So C/C++ allows you to explicitly disable it via the volatile keyword.
The fact above that flag_ was a member variable, and not a global variable (nor static global) does not matter. The explanation after the example gives the correct reasoning even if you're dealing with global variables (and static global variables).
A common misconception is that declaring a variable volatile is sufficient to ensure thread safety. Operations on the variable are still not atomic, even though they are not "cached" in registers
volatile with pointers:
Volatile with pointers, works like const with pointers.
A variable of type volatile int * means that the variable that the pointer points to is volatile.
A variable of type int * volatile means that the pointer itself is volatile.
They are different things. I'm not an expert in volatile semantics. But i think it makes sense what is described here.
Global
Global just means the identifier in question is declared at file-scope. There are different scopes, called function (where goto-labels are defined in), file (where globals reside), block (where normal local variables reside), and function prototype (where function parameters reside). This concept just exist to structure the visibility of identifiers. It doesn't have anything to do with optimizations.
Static
static is a storage duration (we won't look at that here) and a way to give a name declared within file scope internal linkage. This can be done for functions or objects only required within one translation unit. A typical example might be a help function printing out the accepted parameters, and which is only called from the main function defined in the same .c file.
6.2.2/2 in a C99 draft:
If the declaration of a file scope
identifier for an object or a function
contains the storage class specifier
static, the identifier has internal
linkage.
Internal linkage means that the identifier is not visible outside the current translation unit (like the help function of above).
Volatile
Volatile is a different thing: (6.7.3/6)
An object that has volatile-qualified
type may be modified in ways unknown to
the implementation or have other
unknown side effects. Therefore any
expression referring to such an object
shall be evaluated strictly according
to the rules of the abstract machine,
as described in 5.1.2.3. Furthermore,
at every sequence point the value last
stored in the object shall agree with
that prescribed by the abstract
machine, except as modified by the
unknown factors mentioned
previously.
The Standard provides an excellent example for an example where volatile would be redundant (5.1.2.3/8):
An implementation might define a
one-to-one correspondence between
abstract and actual semantics: at
every sequence point, the values of
the actual objects would agree with
those specified by the abstract
semantics. The keyword volatile
would then be redundant.
Sequence points are points where the effect of side effects concerning the abstract machine are completed (i.e external conditions like memory cell values are not included). Between the right and the left of && and ||, after ; and returning from a function call are sequence points for example.
The abstract semantics is what the compiler can deduce from seeing only the sequence of code within a particular program. Effects of optimizations are irrelevant here. actual semantics include the effect of side effects done by writing to objects (for example, changing of memory cells). Qualifying an object as volatile means one always gets the value of an object straight from memory ("as modified by the unknown factors"). The Standard doesn't mention threads anywhere, and if you must rely on the order of changes, or on atomicity of operations, you should use platform dependent ways to ensure that.
For an easy to understand overview, intel has a great article about it here.
What should i do now?
Keep declaring your file-scope (global) data as volatile. Global data in itself does not mean the variables' value will equal to the value stored in memory. And static does only make your objects local to the current translation unit (the current .c files and all other files #include'ed by it).
The "volatile" keyword suggests the compiler not to do certain optimizations on code involving that variable; if you just use a global variable, nothing prevents the compiler to wrongly optimize your code.
Example:
#define MYPORT 0xDEADB33F
volatile char *portptr = (char*)MYPORT;
*portptr = 'A';
*portptr = 'B';
Without "volatile", the first write may be optimized out.
The volatile keyword tells the compiler to make sure that variable will never be cached. All accesses to it must be made in a consistent way as to have a consistent value between all threads. If the value of the variable is to be changed by another thread while you have a loop checking for change, you want the variable to be volatile as there is no guarantee that a regular variable value won't be cached at some point and the loop will just assume it stays the same.
Volatile variable on Wikipedia
They may not be in different in your current environment, but subtle changes could affect the behavior.
Different hardware (more processors, different memory architecture)
A new version of the compiler with better optimization.
Random variation in timing between threads. A problem may only occur one time in 10 million.
Different compiler optimization settings.
It is much safer in the long run to use proper multithreading constructs from the beginning, even if things seem to work for now without them.
Of course, if your program is not multi-threaded then it doesn't matter.
I +1 friol's answer. I would like to add some precisions as there seem to be a lot of confusions in different answers: C's volatile is not Java's volatile.
So first, compilers can do a lot of optimizations on based on the data flow of your program, volatile in C prevents that, it makes sure you really load/store to the location every time (instead of using registers of wiping it out e.g.). It is useful when you have a memory mapped IO port, as friol's pointed out.
Volatile in C has NOTHING to do with hardware caches or multithreading. It does not insert memory fences, and you have absolutely no garanty on the order of operations if two threads do accesses to it. Java's volatile keyword does exactly that though: inserting memory fences where needed.
volatile variable means that the value assinged to it is not constant, i.e if a function containing a volatile variable "a=10" and the function is adding 1 in each call of that function then it will always return updated value.
{
volatile int a=10;
a++;
}
when the above function is called again and again then the variable a will not be re-initialised to 10, it will always show the updated value till the program runs.
1st output= 10
then 11
then 12
and so on.