2

I read everything and everywhere I could about "compile time constants" in C, and I cannot yet give an explanation to the following:

const short testArray[2]={1,2};
//void IndeedConst(void){ testArray[0]=3; } //correctly reports "error: assignment of read-only location 'testArray[0]'"
const short testItem=testArray[0]; //why "error: initializer element is not constant"??

so the compiler is complaining that testArray[0] is read only/const and at the same time it is stating that testArray[0] is not constant! I did answer myself "evidently the dereferencing operator [ ] cannot work "on compile time" constant initialization, then whyever this lines would compile with no errors?

const short* testItem=&(testArray[1]);

also note that here I am getting the address of the 2nd item in the array. therefore the "compile time" constant initialization can dereference with no problem!
What's an explanation for this?

Snake
  • 29
  • 5
  • 1
    `const short testItem=testArray[0];` shouldn't produce an error. Please post an MCVE. – juanchopanza Feb 01 '15 at 14:46
  • @mafso Not for me with clang 3.5 in c89, c99 or c11 mode. Similarly [with gcc](http://ideone.com/gWHhkw). What compiler and C standard are you compiling with? – juanchopanza Feb 01 '15 at 14:49
  • @mafso To clarify: I know this is C. I never said anything about C++. – juanchopanza Feb 01 '15 at 14:57
  • Quoting an answer to another question: "in C language the term "constant" refers to literal constants (like 1, 'a', 0xFF and so on) and enum members. Const-qualified objects (of any type) are not constants in C language terminology. They cannot be used in initializers of objects with static storage duration, regardless of their type." (http://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when-trying-to-initialize-variable-w) –  Feb 01 '15 at 14:59
  • 1
    @juanchopanza It won't compile if the variables have static storage duration (i.e. if they are globals or static locals). – interjay Feb 01 '15 at 15:00
  • @interjay: which they obviously are in this case since OP posted a parameterless function using one of them directly. –  Feb 01 '15 at 15:01
  • @mafso I compile with `cc -Wall -Wextra -Wconversion -pedantic-errors -std=c99`. The variables have automatic storage. Maybe that is the reason for the discrepancy. – juanchopanza Feb 01 '15 at 15:01
  • @juanchopanza. this is C code, carefully written inside a .c file, I am trying to compile with gcc version 4.5.1 (XC16, Microchip v1.23) Build date: Sep 25 2014; unfortunately I have no chance to use C++ for PIC MCU – Vittorio G. Feb 01 '15 at 15:02
  • 1
    OK, got it. I thought your variables were automatic, and they are static. That makes a difference in C. – juanchopanza Feb 01 '15 at 15:03

1 Answers1

4

For variables with static storage duration, the initializer must consist of constant expressions. These include:

  • An arithmetic constant expression: This can only have operands that are integer/enum/character/floating constants, and sizeof expressions. They may not refer to the values of other variables.
  • A null pointer constant.
  • An address constant, optionally added to an integer constant expression. This address constant can be null, point to a function, or point to an object with static storage duration. The standard allows using operators such as [] and & as long as you do not refer to the value of an object.

In this case, testArray[1] is not a constant expression due to referring to the value stored in another variable, but &testArray[1] is an address constant and is a valid constant expression.

Reference: C99 standard, section 6.6.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • Thank you very much, this is what I understood: the initializer CAN NOT contain const variable (such as testArray[0]), although they are const and static (that's not so intuitive); the [..] operator in the second definition (&testArray[1]) works simply because it stands for &testArray + 1, that is 'optionally added to an integer constant expression' (again not so intuitive); finally explained something worrying me for hours, thanks again! – Vittorio G. Feb 01 '15 at 15:26
  • Just a final note: don't you think the compiler response "error: initializer element is not constant" is completely misleading? the initializer element IS constant! the point is that it is not a valid initializer (being a const variable) – Vittorio G. Feb 01 '15 at 15:31
  • @VittorioG. It's confusing, but they are using the word "constant" to mean a constant expression as described above. The keyword `const` marks a value as non-modifiable in runtime and it is not considered "constant". The reason for this confusing wording is that C originally had no `const` keyword, so the only meaning of "constant" was as described above. – interjay Feb 01 '15 at 15:36