Pregunta Inicializar una variable a su propio valor indefinido


En C, ¿tiene sentido inicializar una variable a su propio valor? Si es así, ¿para qué?

Permíteme elaborar. En las fuentes de Git hay algunos ejemplos de inicialización de una variable a su propio valor indefinido, como se ve en transport.c o wt-status.c. Eliminé las asignaciones de esas declaraciones y realicé pruebas. Al no ver regresiones, pensé que esas asignaciones eran redundantes.

Por otro lado, hice algunas pruebas simples con GCC 4.6 y Clang 2.9.

#include <stdio.h>
int main() {
  printf("print to increase probability of registers being non-zero\n");
  int status = status;
  return printf("%i\n", status);
}

Compilando con -Wall -std=c99 Y varios -O niveles no imprime advertencias y muestra que status == 0. Clang con un nivel de optimización distinto de cero imprime algunos valores de basura. Me hace inferir que los resultados de tales expresiones no están definidos.

Me puedo imaginar que tal asignación puede suprimir una variable no inicializada advertencia, pero no es el caso para los ejemplos tomados de Git. Eliminar asignaciones no introduce ninguna advertencia.

¿Son estas asignaciones un comportamiento indefinido? Si no, ¿para qué los usas?


He sugerido el cambio en la lista de correo de Git. Esto es lo que aprendí.


20
2017-11-27 07:51


origen


Respuestas:


Esto compila porque Estándar C99 §6.2.1 / 7 dice:

Cualquier identificador que no sea una estructura, unión o etiqueta de enumeración "tiene un alcance que comienza justo después de la finalización de su declarador". El declarador es seguido por el inicializador.

Sin embargo, el valor de status es Indeterminado. Y no puede confiar en que se inicialice a algo significativo.

¿Como funciona?
int status crea un espacio para que la variable exista en la pila (almacenamiento local) que luego se lee para realizar status = status, status podría inicializarse a cualquier valor que estuviera presente en el marco de pila.

¿Cómo puedes protegerte de tal autoinicialización?
gcc proporciona una configuración específica para detectar autoinicializaciones y reportarlas como errores:

-Werror = sin inicializar -Winit-self

¿Por qué se usa en este código?
La única razón por la que puedo pensar que se está utilizando en dicho código es suprimir la advertencia de la variable no utilizada por ejemplo: transport.c, si el control nunca entra dentro del while bucle entonces en ese flujo de control cmp no se utilizará y el compilador debe generar una advertencia para ello. El mismo escenario parece ser con status variable en wt-status.c 


11
2017-11-27 08:13



Para mí, la única razón para una inicialización autoasignada es evitar una advertencia.

En el caso de su transport.c, Ni siquiera entiendo por qué es útil. Me habría ido cmp sin inicializar

Mi propio hábito (al menos en C) es inicializar todas las variables, generalmente a 0. El compilador optimizará la inicialización innecesaria, y tener todas las variables inicializadas facilita la depuración.

Hay un caso en el que quiero que una variable permanezca sin inicializar, y puedo autoasignarla: semillas aleatorias:

 unsigned myseed = myseed;
 srand(myseed);

1
2017-11-27 08:03



En MacOS X 10.7.2, probé este ejemplo, con el resultado mostrado ...

$ cat x3.c
#include <stdio.h>

int status = -7;

int main()
{
    printf("status = %d\n", status);
    int status = status;
    printf("status = %d\n", status);
    return 0;
}
$ make x3
gcc -O -std=c99 -Wall -Wextra  x3.c -o x3  
$ ./x3
status = -7
status = 1787486824
$

El espacio de pila donde el local status en main() ha sido utilizado por printf() entonces la autoinicialización copia la basura.


1
2017-11-27 08:04



creo status = status no cambia el valor de status (comparado con int status;) Creo que se usa para suprimir el unused variable advertencia.


0
2017-11-27 08:27