La asignación de miembros de la estructura causa un error de syntax cuando no está dentro de una función

Quiero asignar un valor particular a una variable global (definida por el usuario) en el lenguaje de progtwigción C. Cuando hago esto desde cualquier otra función o función principal, está bien. Pero cuando lo hago desde el espacio global (fuera de cualquier función), se está generando el siguiente error de comstackción:

[expected '=', ',', ';', 'asm' or '__attribute__' before '.' token] 

A continuación se muestra un fragmento de código que causa un problema:

 #include  #define MAX_SIZE 5 typedef struct { int val[MAX_SIZE]; int top; }stack_t; stack_t s; s.top = -1; // <== Initialization from here is causing compilation error main() { //s.top = -1; < === Initialization from here is fine printf("s.top =%d\n", s.top); return 0; } 

Pero el mismo tipo de asignación para variables enteras no es solo advertir

 #include  int i,j,k,l; k=10; main() { printf("i= %d, j=%dk=%dl=%d\n", i, j, k, l); return 0; } 

¿Alguien puede por favor decir la razón de esto?

El error de la asignación de s.top no es sorprendente. No es una inicialización sino una asignación, y esos son conceptos diferentes en C. No puede tener asignaciones fuera de las funciones.

La parte interesante aquí es que parece que puede hacer una asignación de la variable entera k. ¡Pero eso es una ilusión, ya que en ese caso no es una tarea sino una inicialización!

La línea

 k = 10; 

se interpreta no como una asignación sino como una definición de variable. Un indicio de esto es que GCC da las advertencias “la definición de datos no tiene tipo o clase de almacenamiento” y “el valor predeterminado es ‘int’ en la statement de ‘k'”. Así que la línea podría escribirse como

 int k = 10; 

Como escribió Matt en un comentario a continuación, omitir el tipo de datos como este parece ser una extensión GCC, y no algo que permita el estándar.

(Por cierto, encienda las advertencias en su comstackdor, ¡y preste atención a ellas!)

Pero espera, ¿no existía ya una definición de k en la línea anterior y no puedes tener más de una definición, verdad?

Primero, recuerde que C hace una distinción entre definiciones y declaraciones. Una definición de una variable es cuando “creas” la variable y, opcionalmente, le das un valor inicial. Una statement es cuando le dices al comstackdor que la variable existe, y su nombre y tipo de datos, pero la definición está en otra parte. Puede tener una definición y una o más declaraciones de la misma variable. Por ejemplo:

 int xxx = 10; // This is the definition of xxx int xxx; // This is a declaration of xxx int xxx; // Another delaration of xxx 

Pero a veces el comstackdor no puede determinar si lo que ve es una statement o una definición, y luego se interpreta como una “definición provisional”, o en otras palabras, tal vez una definición, tal vez solo una statement, decidiremos más adelante “. Por ejemplo:

 int yyy; 

¿Es esa una definición de la variable yyy (sin un valor inicial), o es solo una statement, donde la definición se encontrará en otra parte? El comstackdor no sabe, por lo que espera para decidir, y llama a esto una definición provisional.

Cuando el comstackdor ve su primera statement de k (junto con las otras variables i, j y l) se interpreta como una definición tentativa, y cuando se encuentra la definición posterior, esa definición tentativa de k se decidirá como una statement, No es una definición.

El código C tiene que estar dentro de una función. Puede declarar un global fuera de una función, pero no puede escribir una statement de asignación fuera de una función. Es decir, puede establecer el valor inicial como parte de la statement de la estructura, pero no puede cambiarlo. Aquí su statement es sólo el “stack_t s;” línea.

Todo en C termina comstackndo símbolos en un formato binario (un ejemplo sería el formato ELF). Los símbolos tienen nombres, por lo que las funciones se denominan fragmentos de código y los globales se denominan fragmentos de datos. No hay fragmentos “flotantes libres” en el binario comstackdo, todo tiene que ir bajo un nombre.

En el modelo C, el código que flota fuera de una función no tiene sentido porque C no tiene un lugar donde ejecutar ese código. C nunca ejecuta un archivo de la forma en que lo hace bash o Python o javascript; solo ejecuta binarios. Así que solo ejecuta funciones nombradas. Los archivos solo se conocen en tiempo de comstackción y no en tiempo de ejecución.

Inicializar lo externo a lo main es la razón de ese error. Puedes hacer eso usando así.

 stack_t s={.top=-1}; 

Te permitirá hacer la inicialización mientras declaras. Consulte este enlace. o esto puede ser útil.

Hay diferencias entre la asignación y la inicialización . Debe tener en cuenta que, la asignación no se puede realizar fuera de una función. La statement

 s.top = -1; 

Es una tarea no una inicialización .

C99 y este último proporcionan la inicialización designada de estructuras y matrices. Por lo tanto, puede inicializar solo el miembro top de las estructuras como

 stack_t s = { .top = -1 }; 

y otros miembros serán inicializados a 0 por el comstackdor.

En el espacio global, solo puede inicializar y declarar las variables, pero no puede asignar el valor a las variables. En su código, está asignando el valor al miembro de la estructura, por lo que su error de lanzamiento y el mismo es válido para los enteros de su código siguiente.

Pruebe el siguiente código en el espacio global y funciona bien:

 typedef struct { int val[MAX_SIZE]; int top; }stack_t; stack_t s={{},-1}; main() { printf("s.top=%d",s.top); return 0; }