Initializer element is not constant in C [duplicate] - c

This question already has answers here:
Error "initializer element is not constant" when trying to initialize variable with const
(8 answers)
Closed 2 years ago.
I'm coming from javascript/php/python and probably I'm missing something, here is the code:
const int a = 50;
const int c = 100;
const int d = 100;
int endX = c + a;
int endY = d;
int startX, startY, b;
I get
ex1.4.c:6: error: initializer element is not constant
ex1.4.c:7: error: initializer element is not constant
Does someone have an explanation?

Unfortunately, in C const variables are not really const.
Below are the extracts from the c99 standard.
6.7.8 Initialization
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string
literals.
The constants are defined as follows:
6.4.4 Constants
Syntax
constant:
integer-constant (e.g. 4, 42L)
floating-constant (e.g. 0.345, .7)
enumeration-constant (stuff in enums)
character-constant (e.g. 'c', '\0')
The standard defines constant expressions as follows:
6.6 Constant expressions
(7) 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 an object type plus or minus an integer constant expression.
(8) An arithmetic constant expression shall have an arithmetic type and shall
only have operands that are integer constants, floating constants,
enumeration constants, character constants, and sizeof expressions.
Cast operators in an arithmetic constant expression shall only convert
arithmetic types to arithmetic types, except as part of an operand to
a sizeof operator whose result is an integer constant.
Thus, c and a are not constant expressions and cannot be used as initializers in your case.

const expressions must be a compile time constant in C unlike in C++ therefore c+a can't be used as a constant. The usual way to handle this problem in C is to use the preprocessor instead:
#define A 50
#define C 100
#define D 100
int endX = C + A;
int endY = D;
int startX, startY, b;

If you are declaring endX as a global variable the error makes sense.
The reason is that global variables are initialized in compiling time, and you are trying to initialize endX as an operation that must be done in execution time.

Yeah, you can't initialize something to a variable. The compiler does the initialization and at compile time it doesn't know the value of c+a;
The int x = 1; type initialization is fine, the compiler just puts a 1 at the address of x in the object code.
To initialize something to c+a, you want to do it at runtime, in the startup code in c or constructor in C++.

In C programming langages, objects with static storage duration must be initialized with constant expressions (or aggregate containing constant expressions). If endX has static storage duration, its initializer (c+a) is not a constant expression (i.e. the expression cannot be evaluated during translation phase).

Related

why am i getting warnings errors due to assignment of a variable's address to a pointer in the global scope?

this the snip of the warning i was getting when i tried to compile the program.I am just getting started with pointers and this following program is being flagged by compiler for some reason I am not able comprehend. the code is as follows:
#include <stdio.h>
int dec = 0;
int *d;
d = &dec;
int main() {
return 0;
}
there is no error when I am stuffing these declarations in to main's body. the version of gcc I am using is gcc version 12.2.0(downloaded using MSYS2) and code editor MS visual code.can anybody post an explanation for this?
as i have stated above i have randomly started typing a program to get familiar with pointers, i expected there to be no variation in the treatment of pointers regardless of where they are being declared and intialised.
You're attempting to perform an assignment outside of a function, which is not allowed. What you can do is initialize:
int *d = &dec;
You may use only declarations in file scopes.
In the provided program you are using an assignment statement
d = &dec;
in the file scope. So the compiler issues an error.
Instead you could write for example
#include <stdio.h>
int dec = 0;
int *d = &dec;
int main( void ) {
return 0;
}
As the variable dec has static storage duration then the expression &dec is an address constant and my be used as an initializer for the variable d that also has static storage duration.
From the C Standard (6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals.
and (6.6 Constant expressions)
7 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.
and
9 An address constant is a null pointer, a pointer to an lvalue
designating an object of static storage duration, or a pointer to a
function designator; it shall be created explicitly using the unary
& operator or an integer constant cast to pointer type, or
implicitly by the use of an expression of array or function type. The
array-subscript [] and member-access . and -> operators, the address &
and indirection * unary operators, and pointer casts may be used in
the creation of an address constant, but the value of an object shall
not be accessed by use of these operators.

When I am using const in c language variables [TAILLE_MAX]={3,6,0,8,97,0,5,6,0,8} compiler issue "expression must have a constant value [duplicate]

This question already has answers here:
Can a const variable be used to declare the size of an array in C?
(5 answers)
Closed 1 year ago.
#include <stdio.h>
const int TAILLE_MAX = 10;
int iTableau[TAILLE_MAX]={3,6,0,8,97,0,5,6,0,8};
const int TAILLE_MAX = 10; is not a compile-time expression in C, so it cannot be used as a compile-time array size. Replace the expression with a macro: #define TAILLE_MAX 10
See also this StackOverflow question.
const int something = 100;
does not make the something a constant expression. It is constant variable but not constant expression.
Static storage duration objects sizes and initializers have to be constant expressions
An integer constant expression* shall have integer type and shall
only have operands that are integer constants, enumeration
constants, character constants, sizeof expressions whose results
are integer constants, 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 operator.
(*)An integer constant expression is required in a number of
contexts such as the size of a bit-field member of a
structure, the value of an enumeration constant, and the size
of a non-variable length array. Further constraints that apply to
the integer constant expressions used in conditional-inclusion
preprocessing directives are discussed in 6.10.1
In your case change it to:
#define TAILLE_MAX 10

array bound is not an integer constant before ']' token when it is actually constant

I am trying to have an array, which has a defined size known during compile time.
const uint8_t a[2] = {0, 127}; // Fine
const uint8_t aRange = a[1] - a[0]; // Fine
double sums[aRange]; //Fails
But this fails by gcc with
error: array bound is not an integer constant before ']' token.
As a workaround I intend to use macro variables. But would like to know if there is any logic behind it. There is this answer, which is most related. However, according to the answer, it should have worked.
aRange is a constant integer, but not an integer constant. Isn't English a fun language?
C11 §6.4.4.1 Integer constants
C11 §6.6 Constant expressions ¶6
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.
117) An integer constant expression is required in a number of contexts such as the size of a bit-field member of a structure, the value of an enumeration constant, and the size of a non-variable length array. Further constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing directives are discussed in 6.10.1.
C11 §6.7.6.2 Array declarators — one of the more inscrutable parts of the standard. (¶2 is a constraint; ¶4 and ¶5 specify the semantics of array declarators.)
¶2 If an identifier is declared as having a variably modified type, it shall be an ordinary identifier (as defined in 6.2.3), have no linkage, and have either block scope or function prototype scope. If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.
¶4 If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope;143) such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)
143) Thus, * can be used only in function declarations that are not definitions (see 6.7.6.3).
¶5 If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero. The size of each instance of a variable length array type does not change during its lifetime. Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated.
At file (global) scope, you must have an integer constant expression for the dimensions of an array. In a local variable in C99 or later, what you've written would be OK for a VLA (variable-length array).
You could work around this with:
enum { A_MIN = 0, A_MAX = 127 };
const uint8_t a[2] = { A_MIN, A_MAX };
const uint8_t aRange = a[1] - a[0];
double sums[A_MAX - A_MIN];
In C, you can't write const uint8_t aRange = a[1] - a[0]; at file (global) scope, so your code should have been OK unless you're using an antiquated C compiler that doesn't recognize C99 or later (or it defines __STDC_NO_VLA__).
Jonathan's answer is accepted. As a workaround I used macros though.
#define A_MIN 0
#define A_MAX 127
const uint8_t a[2] = {A_MIN, A_MAX};
const uint8_t aRange = A_MAX - A_MIN;
double sums[aRange];

C - initializer not constant with string literal

I am aware of the limitations for initializers at file-scope in c: you cannot use a variable (even const), functions etc... But I really do not understand why this does not work:
#include <stdlib.h>
#include <stdio.h>
//unsigned long a = "string"[0] > '0'; // this does not compile
unsigned long a = 's' > '0'; // this works fine, output is "a = 1"
int main(void)
{
printf("a = %lu\n",a);
return 0;
}
Why does the line with the string literal gives: error: initializer element is not constant. Are string literals not considered constant? Is there any way to make it work?
Thanks in advance
Your variable has static storage duration, as such and according to N1570 (C11) §6.7.9/p4:
All the expressions in an initializer for an object that has static or
thread storage duration shall be constant expressions or string
literals.
String literals have static storage duration §6.4.5/p6, so their addresses can be considered constant expressions (which is why they are allowed as initializers). But you are trying to access the value at such an address, and the C standard explicitly forbids it. To quote §6.6/p9, emphasis mine:
An address constant is a null pointer, a pointer to an lvalue
designating an object of static storage duration, or a pointer to a
function designator; it shall be created explicitly using the unary &
operator or an integer constant cast to pointer type, or implicitly by
the use of an expression of array or function type. The
array-subscript [] and member-access . and -> operators, the address &
and indirection * unary operators, and pointer casts may be used in
the creation of an address constant, but the value of an object shall
not be accessed by use of these operators.
On the other hand, when you used character constants for comparison, you obtain a valid constant expression.
In C language objects with static storage duration have to be initialized with constant expressions or with aggregate initializers containing constant expressions.
Now here you had basically "string"[0] as an constant expression? But is it so?
The thing is From 6.6p2
A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.
Now after that I checked the translation phases and what it consists of:
It will be clear that none of the expression is evaluated which involves a [] array subscripting over string literal. This literally involves dereferencing an address and getting the vlaue which is not possible to do in translation phases. That's why this error.

why cant we assign a value to global variables using an expression in C ?

In the below code snippet , I am trying to assign a value to a global variable using an expression but it gives the error "initializer element is not constant" ,I am unable to get the logic behind this ,please clarify this .
#include<stdio.h>
int a=8;
int b=a+9;
int main()
{
printf("%d",b);
return 0;
}
The reason is that global variables are initialized in compiling time,
and you are trying to initialize b=a+9; as an operation that must be done in execution time.
You can assign a global variable using an expression. But only inside a function. As said by the compiler/linker, outside a function you can initialize variables only to constant. This is because, outside a function, no code can be executed and the variables are initialized to constant value by the compiler/linker at build time. Note that if you don't init the variable (outside a function), the default initialization is to 0.
To make it work you should write
#include<stdio.h>
int a=8;
int b;
int main()
{
b=a+9;
printf("%d",b);
return 0;
}
As b is of arithmetic type and has static storage duration, its initializer has to satisfy the rules of arithmetic constant expressions (C11 §6.6 Expressions):
8 An arithmetic constant expression shall have arithmetic type and
shall only have
operands that are integer constants, floating constants, enumeration constants, character
constants, sizeof expressions whose results are integer constants, and _Alignof
expressions.
Cast operators in an arithmetic constant expression shall only convert
arithmetic types to arithmetic types, except as part of an operand to a sizeof or
_Alignof operator.
int b=a+9; doesn't.

Resources