Por qué los elementos de inicialización de variables globales del lenguaje C deben ser constantes, mientras que las variables locales pueden no ser constantes

prefacio

(1) Hoy vi una pregunta interesante: en el grupo de comunicación, un internauta preguntó por qué no se pueden dar variables globales a las variables. Aparecerá un mensaje de error de un elemento inicializador no constante, el código es el siguiente

#include <stdio.h>

int a = 1;
int b = a+1; //这里会报错initializer element is not constant

int main(void)
{
    
    
	printf("a = %d\r\n",a);
	printf("b = %d\r\n",b);
	return 0;
}

(2) En términos generales, a las variables globales se les asigna un número constante de forma predeterminada y las variables locales se asignan a una variable. Respecto a las preguntas anteriores, también expresé dudas, así que comencé a buscar información con dudas.

#include <stdio.h>

int a = 1;

int main(void)
{
    
    
	int b = a+1;
	printf("a = %d\r\n",a);
	printf("b = %d\r\n",b);
	return 0;
}

explicar

Ubicación de almacenamiento de variables globales y variables locales

(1) Para aclarar esta pregunta, en primer lugar, necesitamos saber cuál es la diferencia entre variables globales y almacenamiento de variables locales. Para obtener más detalles, consulte: ¿ Por qué la variable global inicializada se almacena en la RAM cuando la RAM obviamente está apagada y perderá datos? Analice en detalle el almacenamiento del programa ;
(2) Debido a que el artículo anterior es relativamente extenso, lo condensaré.
<1>Una variable global a la que se le asigna un valor distinto de 0 eventualmente se almacenará en el segmento .data. Al compilar, se convertirán en datos RW y su valor inicial deberá almacenarse en el área ROM.
<2>La variable local no se compilará en el microcontrolador, es decir, no ocupa espacio cuando el microcontrolador está apagado.
<3> Cuando el microcontrolador esté encendido, se asignará un área de datos estáticos en la RAM para las variables globales. Al mismo tiempo, asigne el valor inicial a la sección .data del área de datos estáticos.
<4> Después de encender la MCU y comenzar a ejecutar el programa, se llama a la función donde existe la variable local. La microcomputadora de un solo chip asignará espacio para las variables locales en la pila y luego asignará el valor inicial que se implementa ejecutando el código durante el proceso de ejecución.
<5> Por lo tanto, podemos sacar una conclusión. Una variable global a la que se le asigna un valor inicial se almacena estáticamente. Para las variables locales a las que se les asignan valores iniciales, los valores iniciales se almacenan dinámicamente.
(4) Después de comprender lo anterior, podemos comprender por qué se puede pasar la asignación de valor inicial de las variables locales, porque es dinámica, por lo que al compilador no le importará. ¿Pero por qué no las variables globales? Esto implica la relación entre los datos almacenados estáticamente y el compilador.

Relacionado con el compilador

(1) Todos sabemos que el compilador puede convertir el lenguaje C en un lenguaje 01 que la máquina puede reconocer. El compilador también tiene algunas funciones que a menudo pasamos por alto.
(2) Para que el programa sea más compacto y refinado, el compilador nos ayudará a lidiar con muchas cosas. Esto lleva a un concepto,Utilice el tiempo del compilador para el tiempo de ejecución.
<1> Tiempo de compilación: el período de tiempo en el que usted (el desarrollador) compila el código.
<2>Tiempo de ejecución: el período de tiempo en el que el usuario ejecuta su software.
(3) Por ejemplo, el siguiente código simple:
<1> Podemos encontrar que int b = 2 + 3; después de la conversión se llama código ensamblador, pasa directamente 5 a b. Esto significa que el compilador realizó un procesamiento aritmético y optimizó el código. se llamaplegado constante.
<2> La operación de sizeof es la misma, el compilador pasará directamente la información de que el int es de 4 bytes a la variable.

inserte la descripción de la imagen aquí

(4) Los dos ejemplos anteriores utilizan la hora del compilador para cambiar la hora del estado de ejecución. Entonces, después de hablar tanto, ¿qué tiene que ver con los elementos de inicialización de variables globales que deben ser constantes?
(5) Como se mencionó anteriormente, el compilador realizará un plegado constante, ¡pero tenga en cuenta que esto es un plegado constante! El plegado constante calculará expresiones constantes durante el tiempo de ejecución del compilador, literales enteros, operador sizeof() (cuando el parámetro no es VLA), constantes de enumeración y varios operadores aritméticos, relacionales/de comparación en todas las operaciones. Cuando todos los números son constantes enteras, el total La expresión se considera una expresión constante entera.

inserte la descripción de la imagen aquí

(6) Sin embargo, descubrimos que el compilador no realizará operaciones variables. Por lo tanto, a la variable global int b = a+1; se le asigna un valor inicial y el compilador no realizará cálculos.

Resumir

(1) Por lo tanto, podemos concluir:
<1> El compilador no puede obtener un valor no constante en el momento de la compilación, solo puede obtener el valor de la variable indirectamente leyendo la dirección de la variable en el tiempo de ejecución, y la variable global está en su El valor debe determinarse en el momento de la compilación.
<2> El valor inicial de la variable local no lo administra el compilador, se asigna en tiempo de ejecución, por lo que el valor inicial se puede asignar a la variable.

Supongo que te gusta

Origin blog.csdn.net/qq_63922192/article/details/132312489
Recomendado
Clasificación