Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not a constant initializer element?

I encountered a confusing case when I was doing semantic analysis for my compiler course.

#include <stdio.h>

int a = "abcd"[2];

int main()
{
    char b = "abcd"[2];

    printf("%d\n%c\n", a, b);

    return 0;
}

GCC says "error: initializer element is not constant" for variable "a".

Why?

like image 282
Yu Cang Avatar asked Mar 28 '17 14:03

Yu Cang


People also ask

What is the meaning of initializer element is not constant?

It's not inside a function, which means it has to be an initializer - which is assigned only when the item is declared - which means it must be a constant value at compile time, which malloc cannot be.

What is not constant in C?

Moreover, in C language, the term "constant" refers to literal constants (like 1 , 'a' , 0xFF and so on), enum members, and results of such operators as sizeof . Const-qualified objects (of any type) are not constants in C language terminology.

Can constant be initialized?

Constant initialization is performed after zero initialization of the static and thread-local objects and before all other initialization. Only the following variables are constant initialized: 1) Static or thread-local references, if it is bound to static lvalue, to a temporary, or to a function.

What is a const variable in C?

The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it.


1 Answers

The C language requires initializers for global variables to be constant expressions. The motivation behind this is for the compiler to be able to compute the expression at compile time and write the computed value into the generated object file.

The C standard provides specific rules for what is a constant expression:

  1. An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator .
  2. More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:
    • an arithmetic constant expression,
    • a null pointer constant,
    • an address constant, or
    • an address constant for a complete object type plus or minus an integer constant expression.

As you can see non of the cases include an array access expression or a pointer dereference. So "abcd"[2] does not qualify as a constant expression per the standard.

Now the standard also says:

  1. An implementation may accept other forms of constant expressions.

So it would not violate the standard to allow "abcd"[1] as a constant expression, but it's also not guaranteed to be allowed.

So it's up to you whether or not to allow it in your compiler. It will be standard compliant either way (though allowing it is more work as you need another case in your isConstantExpression check and you need to actually be able to evaluate the expression at compile time, so I'd go with disallowing it).

like image 58
sepp2k Avatar answered Oct 06 '22 01:10

sepp2k