Error "el elemento inicializador no es constante" al intentar inicializar la variable con const
Recibo un error en la línea 6 (inicializar my_foo en foo_init) del siguiente programa y no estoy seguro de entender por qué.
typedef struct foo_t {
int a, b, c;
} foo_t;
const foo_t foo_init = { 1, 2, 3 };
foo_t my_foo = foo_init;
int main()
{
return 0;
}
Tenga en cuenta que esta es una versión simplificada de un proyecto más grande de varios archivos en el que estoy trabajando. El objetivo era tener una única constante en el archivo objeto, que varios archivos pudieran usar para inicializar una estructura de estado. Dado que es un destino integrado con recursos limitados y la estructura no es tan pequeña, no quiero varias copias del código fuente. Preferiría no usar:
#define foo_init { 1, 2, 3 }
También estoy intentando escribir código portátil, por lo que necesito una solución que sea C89 o C99 válida.
¿Tiene esto que ver con los ORG en un archivo objeto? ¿Que las variables inicializadas van a un ORG y se inicializan copiando el contenido de un segundo ORG?
Tal vez solo necesite cambiar mi táctica y hacer que una función de inicialización haga todas las copias al inicio. ¿A menos que haya otras ideas por ahí?
En lenguaje C, los objetos con duración de almacenamiento estático deben inicializarse con expresiones constantes o con inicializadores agregados que contengan expresiones constantes.
Un objeto "grande" nunca es una expresión constante en C, incluso si el objeto se declara como const
.
Además, en lenguaje C, el término "constante" se refiere a constantes literales ( como 1
, etc.), miembros de enumeración y resultados de operadores como . Los objetos calificados const (de cualquier tipo) no son constantes en la terminología del lenguaje C. No se pueden utilizar en inicializadores de objetos con duración de almacenamiento estático, independientemente de su tipo.'a'
0xFF
sizeof
Por ejemplo, esto NO es una constante
const int N = 5; /* `N` is not a constant in C */
Lo anterior N
sería una constante en C++, pero no es una constante en C. Entonces, si intentas hacer
static int j = N; /* ERROR */
obtendrá el mismo error: un intento de inicializar un objeto estático con una no constante.
Esta es la razón por la que, en lenguaje C, usamos predominantemente #define
para declarar constantes con nombre y también recurrimos a #define
para crear inicializadores agregados con nombre.
Es una limitación del idioma. En la sección 6.7.8/4:
Todas las expresiones en un inicializador para un objeto que tiene una duración de almacenamiento estático serán expresiones constantes o cadenas literales.
En la sección 6.6, la especificación define lo que debe considerarse una expresión constante. En ninguna parte se indica que una variable constante debe considerarse una expresión constante. Es legal que un compilador extienda esto ( 6.6/10 - An implementation may accept other forms of constant expressions
), pero eso limitaría la portabilidad.
Si puedes cambiarlo my_foo
para que no tenga almacenamiento estático, estaría bien:
int main()
{
foo_t my_foo = foo_init;
return 0;
}
2021: Para quienes llegan a esta publicación debido a arm-none-eabi-gcc.exe
un error de compilación en MCU STM32:
cambie su cadena de herramientas a gnu-tools-for-stm32.9-2020-q2-update
.
A partir de GCC V8.1+, se admite el inicializador constante anidado y se compilará el siguiente código.
const int a = 1;
const int b = a +1;
typedef struct foo_t {
int a, b, c;
} foo_t;
const foo_t foo_init = { 1, 2, 3 };
foo_t my_foo = foo_init;
int main()
{
return 0;
}
arm-none-eabi-gcc.exe
¡ Se gnu-tools-for-stm32.7-2018-q2-update
basa en gcc v7.3.1
y el código anterior no se compilará! Pero gnu-tools-for-stm32.9-2020-q2-update
usa gcc v9.3.1
y compilará.
Para obtener más información, consulte estos: ¿
Por qué "el elemento inicializador no es una constante"... ya no funciona?
y
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960#c18
Solo a modo de ilustración mediante comparación y contraste. El código es de http://www.geeksforgeeks.org/g-fact-80/ / El código falla en gcc y pasa en g++ /
#include<stdio.h>
int initializer(void)
{
return 50;
}
int main()
{
int j;
for (j=0;j<10;j++)
{
static int i = initializer();
/*The variable i is only initialized to one*/
printf(" value of i = %d ", i);
i++;
}
return 0;
}