En cuestión Declaración diferencia? se preguntó cuál es la diferencia entre
int i; for (i=0; i<100; i++) { //some loop.... }y:
for (int i=0; i<100; i++) { //some loop.... } Las respuestas son claras; el segundo es C99 y el alcance de i se limita al ciclo. No tengo C99, por lo que no puedo probar y, por lo tanto, hago una pregunta: ¿cuál sería la resolución en el siguiente caso?
int i = 32; for (int i=i; i<100; i++) { // some loop } ¿Se inicializaría el "nuevo" i con el "antiguo" i ? ¿O la i antigua ya sería inaccesible porque ya se ha declarado una i nueva?
En esta instrucción de bucle for
int i = 32; for (int i = i; i < 100; i++) { // some loop } la variable i declaré en la instrucción for tiene un valor indeterminado. El problema es que tan pronto como se define un declarador (en este caso consiste en el identificador i ) oculta una entidad con el mismo nombre en el alcance dado. Así que en esta declaración
int i = i; la variable i se refiere a sí misma en el lado derecho de = .
Otro ejemplo parecido. Supongamos que tiene un typedef.
typedef int Int;Puede escribir después de su definición
Int Int; En este caso, el nombre Int del objeto de tipo Int oculta la definición de typedef y es posible que aún no escriba
Int Another_Int;porque el compilador emitirá un error.
Según el Estándar C (6.2.1 Alcances de los identificadores)
4 ...Si el declarador o especificador de tipo que declara el identificador aparece dentro de un bloque o dentro de la lista de declaraciones de parámetros en una definición de función, el identificador tiene alcance de bloque, que termina al final del bloque asociado.
Una forma más clara está escrita en el Estándar C++ (3.3.2 Punto de declaración)
1 El punto de declaración de un nombre es inmediatamente después de su declarador completo (Cláusula 8) y antes de su inicializador (si lo hay), excepto como se indica a continuación. [ Ejemplo:
int x = 12; { int x = x; }Aquí la segunda x se inicializa con su propio valor (indeterminado). —fin del ejemplo]
Tenga en cuenta que en este fragmento de código
int i = 10; { int i[i]; } dentro de la declaración compuesta se declara una matriz int i[10]; esa es la variable externa i se usa como el tamaño de la matriz porque la variable interna i se declarará solo cuando se complete su declarador.
Consulte C11 6.8.5.3 : "Si la cláusula 1 es una declaración, el alcance de los identificadores que declara es el resto de la declaración y el bucle completo, incluidas las otras dos expresiones".
La segunda i se refiere a la i definida, no a la anterior.
Todo es UB porque está utilizando el valor de i (la i se define dentro del bucle) sin una asignación previa (o inicialización).
Edite con un ejemplo de trabajo (pero diferente)
Todavía puede usar el valor anterior mediante el uso de un puntero
int i = 42; int *old_i = &i; for (int i = *old_i; i < 50; i++) printf("%d ", i);No, en cualquier contexto algo como
int i=i; es una mala idea, ya que el segundo i es el mismo objeto que el primero y aún no está inicializado.
Si insistieras, podrías hacer algo como
int tmp=i, i=tmp;para tener el efecto que deseas.