¿Hay alguna diferencia entre inicializar una variable y asignarle un valor inmediatamente después de la statement?

Suponiendo un comstackdor puramente no optimizador, ¿hay alguna diferencia en el código de máquina entre inicializar una variable y asignarle un valor después de la statement?

Método de inicialización :

int x = 2; 

Método de asignación :

 int x; x = 2; 

Usé GCC para generar el ensamblaje generado para estos dos métodos diferentes y ambos dieron como resultado una sola instrucción de máquina:

 movl $2, 12(%esp) 

Esta instrucción solo establece la memoria mantenida por la variable x al valor de 2 . GCC puede estar optimizando esto porque puede reconocer el resultado final de las operaciones; pero creo que esta es la única manera de interpretar las dos versiones. Mi razonamiento es que ambas versiones hacen lo mismo: establecer una parte de la memoria en un valor específico.

¿Por qué es entonces que a menudo se hace una distinción entre los términos ” inicialización ” y ” asignación ” si el código de máquina resultante es el mismo?

¿Se utiliza el término ” inicialización ” únicamente para diferenciar variables que tienen un valor específico asignado sobre aquellas variables (no inicializadas) que tienen cualquier valor de basura que quedó en la memoria?

El comportamiento debe ser idéntico, pero cualquier diferencia en el código generado realmente depende del comstackdor.

Por ejemplo, el comstackdor podría generar esto para la variable inicializada:

 somefunction: pushl %ebp movl %esp, %ebp pushl $2 ; allocate space for x and store 2 in it ... 

y esto para la variable sin inicializar, pero luego asignada:

 somefunction: pushl %ebp movl %esp, %ebp subl $4, %esp ; allocate space for x ... movl $2, -4(%ebp) ; assign 2 to x ... 

El estándar C no exige que el código generado sea idéntico o no idéntico en estos casos. Sólo exige el comportamiento idéntico del progtwig en estos dos casos. Y ese comportamiento idéntico no implica necesariamente un código de máquina idéntico.

Suponiendo un comstackdor puramente no optimizador, ¿hay alguna diferencia en el código de máquina entre inicializar una variable y asignarle un valor después de la statement?

Por supuesto.

  • char fubar[] = "hello world"; es válida.
  • char fubar[]; fubar = "hello world"; no es.

¿Más?

  • int fubar[128] = { [60] = 42 }; es válida.
  • int fubar[128]; fubar = { [60] = 42 }; no es.

¿Más?

  • struct foo bar = { .foo = 13, .bar = 42 }; es válida.
  • struct foo bar; bar = { .foo = 13, .bar = 42 }; no es.

¿Más?

  • const int fubar = 0; es válida.
  • const int fubar; fubar = 0; no es.

Podría seguir y seguir … Por lo tanto, el código de máquina puede existir para uno, mientras que lo más probable es que no lo sea para el otro. En ese sentido, ¿alguna vez has oído hablar de una implementación de C que no sea un comstackdor?

¿Por qué es entonces que a menudo se hace una distinción entre la inicialización y la asignación si el código de máquina resultante es el mismo?

El concepto de variables en el lenguaje de progtwigción C es demasiado alto para la representación de código de máquina de bajo nivel. En el código de máquina, los registros no tienen scope. C agregó el scope, por no mencionar la fusión de tipos y muchos de los otros aspectos relacionados con las variables, junto con la inicialización (que se puede ver en los ejemplos anteriores es directa, pero desafortunadamente no es lo mismo).

¿Se utiliza el término “inicialización” únicamente para diferenciar variables que tienen un valor específico asignado sobre aquellas variables (no inicializadas) que tienen cualquier valor de basura que quedó en la memoria?

Aunque una variable que está “inicializada” no contendrá ningún “valor de basura” (o representaciones de trampa), este no es el único efecto que tiene.

En mi primer ejemplo, la inicialización proporcionará el tamaño de la matriz incompleta. El equivalente al uso del operador de asignación requeriría proporcionar explícitamente la longitud de la matriz y usar strcpy , lo que resulta bastante tedioso.

En mi segundo ejemplo, el int en el índice 60 se inicializará a 40, mientras que los elementos restantes, de lo contrario no inicializados, se inicializarán a 0. El equivalente que utiliza el operador de asignación también sería bastante tedioso.

En mi tercer ejemplo, los miembros foo y bar se inicializarán a 13 y 42, mientras que los miembros restantes, de lo contrario no inicializados, se inicializarán a 0. El equivalente usando el operador de asignación sería bastante tedioso, aunque ocasionalmente utilizo un literal compuesto para lograr Un resultado similar.

En mi cuarto ejemplo, la inicialización establece el valor que la variable contendrá para toda su vida. Ninguna variable es posible para esta variable.

Una distinción importante entra en juego cuando agregas un calificador const :

 int const x = 2; 

es válido C

 int const x; x = 2; 

no es Otra diferencia importante es para las variables static :

 static int x = f(); 

no es válido C

 static int x; x = f(); 

es válida.

 int x = 2; 

La computadora creará la variable x y le asignará el valor 2 casi en el mismo momento .


 int x; x = 2; 

La computadora creará la variable x. Y luego le asignará un valor 2. Parece que no hay ninguna diferencia, pero

… supongamos que su código es así:

 int x; {some operators}; x = 2; 

es posible que la computadora tenga que acceder a la variable x para asignarle el valor 2. Esto significa que, mientras se ejecuta el progtwig, la computadora dedicará más tiempo a acceder a x para asignarle algún valor, a diferencia de si va a crear una variable y evaluar esta variable en este momento .

De todos modos, Deitel HM, Deitel PJ describen esto en C Cómo progtwigr .