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.
Related
I was referring to the book "Theory and Problems of Programming with C" by Gottfried (Schaum's Outline series, 2nd Edition, 1996).
On page number 243 section 9.1 in chapter 9 on Arrays, it says:
Automatic arrays, unlike automatic variables, cannot be initialized. However, external and static array definitions can include the assignment of initial values if desired.
I did not understand the meaning of this highlighted statement. I tried to initialize array (with and without auto keyword) inside the function and do not see any issue with it.
void func1 (void)
{
auto int array1[5] ={1,0,4,1,5};
charVar1='M';
printf("%d", *(array1+4));
}
Added the image of the page
To answer the first part
Automatic arrays, unlike automatic variables, cannot be initialized
assuming the "Automatic arrays" are actually "array data structure of automatic storage duration whose length is determined at run time"
Yes, here what is referred to is called a variable length array. It cannot be initialized as for the simple logic, the size is determined at runtime.
To quote the C11 standard, chapter §6.7.9, Initialization (emphasis mine)
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
Otherwise, for a local variable without any storage class specifier, defaults to auto and an automatic array of non-VLA type, can be initialized, for sure.
Trivial demonstration that the statement is actually wrong (as opposed to e.g. array-initialization being a common but non-standard extension):
void doSomethingWithArray(size_t sz, int arr[static sz]);
int main(void) {
doSomethingWithArray(5,
(int[]){ 1, 2, 3, 4, 5 }
);
}
An anonymous array is created with automatic storage duration within the scope of main. Since it is anonymous, there is no way for code within main to refer to it to set element values. The only way to put values into this particular automatic array is via initialization. This feature - being able to initialize automatic arrays - is therefore legal, standard, and necessary.
QED.
Given that this book is rather ancient, the concepts of VLAs and compound literals were not invented.
Automatic variables is the formal term for local variables. There's even the keyword auto for it, but it is one of the most superfluous keywords in the language, since all local variables are implicitly declared as auto. That is:
{
auto int x = 1;
}
and
{
int x = 1;
}
are 100% equivalent, the auto keywords adds nothing (so nobody uses the former style).
So by the term automatic arrays, the author perhaps simply refers to plain local arrays. As we can see from the example in the question, you can initialize such arrays just fine. The book is incorrect and/or uses the wrong terms.
The author of that book seems confused in general: "assignment of initial values" is the very C definition of initialization. The formal definition can be found in the C standard syntax at 6.7.8, where "assignment-expression" is one of the valid forms for initialization.
I'd recommend to find another book, preferably one that covers the latest C standards C99 and C11.
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!
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.
Pardon me, I am not very good in explaining questions. So I start with example directly
Look at following example
const int a=10;
int *ptr;
int main(){
ptr=&a;
*ptr=100; // program crashes
printf("%d",a);
}
But If I made a slightly change in above code as following
const int a; // uninitialized global variable
Then the above code works fine.
So my question is why compiler behaves differently for uninitialize and initialize global const variables?
I am using gcc for windows (mingw).
You are modifying a const object, and that is simply undefined behavior - so don't do it, and don't ignore compiler warnings.
Now, the actual reason for the different behavior in your particular case is that for const int a=10; the value 10 has to be stored somewhere. Since the variable is const, the linker places it in the .rodata or a similar read only section of the executable. When you're trying to write to a read-only location, you'll get a segmentation fault.
For the uninitialized case, const int a , the a needs to be initialized to zero since it's at file scope (or; a is a global variable). The linker then places the variable in the .bss section, together with other data that also is zero initialized at program startup. The .bss section is read/write and you get no segfault when you try to write to it.
All this is not something you can rely on , this could change with minor modification to the code, if you use another compiler or a newer/older version of your compiler etc.
Global and static variables are initialized implicitly if your code doesn't do it explicitly as mandated by the C standard.
From the doc:
const is a type qualifier. The other type qualifier is volatile. The
purpose of const is to announce objects that may be placed in
read-only memory, and perhaps to increase opportunities for
optimization.
In G++ you will receive the error for the second case ie, const int a;.
6.9.2 External object definitions
Semantics
1 If the declaration of an identifier for an object has file scope and
an initializer, the declaration is an external definition for the
identifier.
2 A declaration of an identifier for an object that has file scope
without an initializer, and without a storage-class specifier or with
the storage-class specifier static, constitutes a tentative
definition. If a translation unit contains one or more tentative
definitions for an identifier, and the translation unit contains no
external definition for that identifier, then the behavior is exactly
as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation
unit, with an initializer equal to 0.
declares a constant integer variable. It means it’s value can’t be modified. It’s value is initially assigned to 10.
If you try to change its value later, the compiler will issue a warning, or an error, depending on your compiler settings.
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.)