ISO: WG21/N0493 ANSI: 94-0106 Authors: John Max Skaller Date: May 1994 Reply to: maxtal@suphys.physics.su.oz.au "CONSTANT EXPRESSIONS" ---------------------- Minor editorial corrections to definition of constant expressions. Problem 1: Initialiser Visibility --------------------------------- The description of constant expressions in the Working Paper is incorrect. The WP states: "A constant-expression can involve only literals, enumerators, const values of integral types initialised with constant expressions and sizeof expressions." Consider: // file 1 extern const int a; char x[a]; // file 2 extern const int a = 42; Under the current rules, there is no error here: a is a const integral type initialised by a constant expression. We doubt any compiler could compile this code correctly. A similar but less striking example is: extern const int a; char x[a]; const int a = 42; Its clear the intent is that the initialiser must be visible at the point of use -- this mechanism is designed to replace use of #define. On examining the ISO C Standard, we find that "A constant expression .. can be used in any place that a constant can be" it is quite plain that for a variable to be used as a constant expression, the initialiser must be visible. Unfortunately, that is not enough specification. Consider: extern const int a; const int b = a; const int a = 42; char x[b]; Here, the initialisers for both a and b are visible and the value 42 of both can be computed at compile time recursively or by back patching. Should we require this? Our answer is no. Whether a variable may be used as a constant expression or not, and its value if it is, should be determinable when the initialiser is seen and not silently adjusted by subsequent definitions. Thus, 'b' above is not a constant expression, so the fragment is ill formed. Editorial Action: Reword the section on constant expressions so it is as plain as day that a variable may be used as a constant expression only if its definition is visible and its initialiser is a constant expression. (This is a necessary but not sufficient condition) ----------------------------------------------------------------------- Problem 2: C allows non-intergral constant expressions ------------------------------------------------------ The description of constant expressions in the Working Paper applies only to const integral types. (Actually, it is misworded, claiming a requirement for a "constant value" which is absurd.) But the ISO C Standard permits floating constant expressions, null pointer constant, address constants and an address plus or minus an arithmetic constant expression. In addition the implementation may accept other forms of constant expression. The definition of constant expression and the forms allowed is crucial in C++ because it affects the order of initialisation. C requires initialisers to be constant expressions. C++ permits dyanamic initialisation. Conceptually, all the "C" initialisations are done first, together with 0 initialisation if no initialiser is given, then the dynamic initialisations are performed. I propose both floating and pointer constants be permitted as per ISO C. I propose all non-volatile const arithmetic and pointer variables are constant expressions, not just combinations of literals and const integral variables. Editorial Action: Incorporate the bulk of the description in the ISO C Standard 6.4. Omit "An implementation may accept other forms of constant expressions". ----------------------------------------------------------------------- Problem 3. Preprocessor constant expressions --------------------------------------------- The ARM and WP incorrectly use the same term "constant expression" in the description of preprocessor expressions. Because of the phases of translation, preprocessor constant expressions cannot depend on const integral variables initialised by constant expressions: const int n = 1; #if n == 1 //?? Editorial Action: Use the term "preprocessor constant expression" to distinguish them from C++ language (integral) constant expressions.