8

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 ?

Community
  • 1
  • 1
tissa
  • 396
  • 2
  • 13

4 Answers4

3

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.

rici
  • 234,347
  • 28
  • 237
  • 341
  • never encountered the term constant expression before ! :( – user12448 Dec 19 '14 at 22:27
  • @user12448: It's the title of section 6.6 of the C standard, so you'd only have to look in the table of contents :) – rici Dec 19 '14 at 22:30
  • where I can find the document please ? :) – user12448 Dec 19 '14 at 22:35
  • 1
    @user12448: The latest available draft is http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf – Keith Thompson Dec 19 '14 at 22:52
  • is `static int var=name_of_variable` a constant expression if not why ? – tissa Dec 20 '14 at 00:51
  • @tanit: In C a variable declared 'static const` is not a "constant expression", because the standard says it is not. In C++, it is because the standard says it is. You can see the difference: `static const int sz=42; int v[sz];` isillegal in C but legal in C++. In neither language is 'static int v' constant, because it is not declared `const` and so its value may be changed. – rici Dec 20 '14 at 02:03
  • int v[sz]; is legal in C99 standard !! besides static int v; cannot get a variable but can get only a number like 0,45,5.. but not any kind of variable like a,var,nb.. during the initialization !! – tissa Dec 20 '14 at 12:44
  • @tanit: I think I misunderstood your question. If I now understand correctly, the answer is that `name_of_variable` is *not* a constant expression, because the standard says it is not. That's what my answer says, too, but I will try to make it clearer. – rici Dec 20 '14 at 16:08
  • @tanit: By the way, `int v[sz];` is not legal in C99 if `v` has static storage duration (for example, if it is a global variable as my example was intended to be). See http://ideone.com/SXXCYR – rici Dec 20 '14 at 16:22
  • in my computer it is only giving a warning. Besides my compiler is a 90 standard with 99 features ! – tissa Dec 20 '14 at 19:20
2

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.
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • what do you mean by **compile time** ? – tissa Dec 19 '14 at 22:02
  • @tanit: Good observation on 1.3. Compile time is when you give the code to the compiler and it produces object files, right before link time when the linker links object files into an executable file. – Mooing Duck Dec 19 '14 at 22:06
  • do you mean compile ( compiler and assembler phase ) or only compiler phase ? please be more specific ? – tissa Dec 19 '14 at 22:23
  • 1
    @tanit: In this context, "compile time" encompasses everything from parsing to code generation (which is what I assume you mean by "assembler phase"). – John Bode Dec 19 '14 at 22:31
2

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.
John Bode
  • 119,563
  • 19
  • 122
  • 198
1

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.

Jason Hu
  • 6,239
  • 1
  • 20
  • 41