Error "el elemento inicializador no es constante" al intentar inicializar la variable con const

Resuelto tomlogic asked hace 14 años • 8 respuestas

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í?

tomlogic avatar Jun 12 '10 00:06 tomlogic
Aceptado

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'0xFFsizeof

Por ejemplo, esto NO es una constante

const int N = 5; /* `N` is not a constant in C */

Lo anterior Nserí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 #definepara declarar constantes con nombre y también recurrimos a #definepara crear inicializadores agregados con nombre.

AnT stands with Russia avatar Jun 11 '2010 18:06 AnT stands with Russia

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_foopara que no tenga almacenamiento estático, estaría bien:

int main()
{
    foo_t my_foo = foo_init;
    return 0;
}
R Samuel Klatchko avatar Jun 11 '2010 18:06 R Samuel Klatchko

2021: Para quienes llegan a esta publicación debido a arm-none-eabi-gcc.exeun 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-updatebasa en gcc v7.3.1y el código anterior no se compilará! Pero gnu-tools-for-stm32.9-2020-q2-updateusa gcc v9.3.1y 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

Zaman avatar Apr 08 '2021 09:04 Zaman

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;
}
achoora avatar Nov 27 '2015 11:11 achoora