2012-03-22 16 views
7

Me tropecé con un comportamiento que me sorprendió:Usando la variable recién declarada en la inicialización (int x = x + 1)?

Al escribir:

int x = x+1; 

en C/C++ - programa (o incluso más compleja expresión que incluya la variable recién creada x) mi gcc/g ++ compila sin errores. En el caso anterior, X es 1 después. Tenga en cuenta que no hay una variable x en el alcance de una declaración anterior.

Así que me gustaría saber si este es el comportamiento correcto (e incluso podría ser útil en alguna situación) o simplemente una pecularidad del analizador con mi versión de gcc o gcc en general.

Por cierto: El siguiente no funciona:

int x++; 
+0

Creo que x es cada vez inicializado a 0 por gcc, pero no se puede confiar en este comportamiento que la norma no pide eso. En algunos sistemas puede dar lugar a basura. – vidit

+0

@EdHeal: No, no he activado las advertencias y no --ansi, pero ambas no cambian la situación (no se emiten advertencias) –

+1

Hay un uso relacionado, legal (pero inusual): 'Node simpleGraph = Node (& simpleGraph) ; 'para crear un gráfico con un nodo vinculado cíclicamente a sí mismo; O incluso más extraño, 'int x = sizeof (x);'. – MSalters

Respuesta

16

Con la expresión:

int x = x + 1; 

la variable x viene a la existencia en la señal de =, por lo que se puede usar en el lado derecho. Cuando "llega a la existencia", me refiero a que la variable existe, pero la parte del inicializador aún no le ha asignado un valor.

Sin embargo, a menos que esté inicializando una variable con duración de almacenamiento estático (por ejemplo, fuera de una función), es un comportamiento indefinido ya que el x que aparece tiene un valor arbitrario.

C++ 03 tiene esto que decir:

El punto de la declaración de un nombre es inmediatamente después de su completa declarador (cláusula 8) y antes de su inicializador (si lo hay) ...

Ejemplo:
int x = 12;
{ int x = x; }
Aquí el segundo x se inicializa con su propio valor (indeterminado).

Ese segundo caso es más o menos lo que tiene en su pregunta.

+0

"entra en existencia" parece un poco vago.Creo que ya está declarado antes de '=', de lo contrario el compilador se quejaría de usar un identificador desconocido. Pero la inicialización, por supuesto, sucede en el '='. – hirschhornsalz

+0

@drhirsch, no creo que sea vago en absoluto, he agregado el bit en el estándar que dice esto. – paxdiablo

+0

Mi segunda frase en mi comentario es una tontería (o frase muy mala). Me refería a la frase "entra en existencia", que se usa como "punto de declaración". Podría entenderse como "punto de inicialización", lo que sería incorrecto. – hirschhornsalz

8

No es, es un comportamiento indefinido .

Está utilizando una variable no inicializada - x. Obtienes 1 por pura suerte, cualquier cosa podría pasar.

FYI, en MSVS recibo una advertencia:

Advertencia 1 C4700 advertencia: sin inicializar variable local 'i' solía

También, en tiempo de ejecución, consigo una excepción, por lo Definitivamente no es seguro.

3

En el primer caso, simplemente usa el valor ya en el lugar en la memoria donde está la variable. En tu caso, esto parece ser cero, pero puede ser cualquier cosa. Usar tal construcción es una receta para desastres y bichos difíciles de encontrar en el futuro.

Para el segundo caso, es simplemente un error de sintaxis. No puede mezclar una expresión con una declaración de variables como esa.

5
int x = x + 1; 

es básicamente

int x; 
x = x + 1; 

Usted acaba de ser la suerte de tener 0 en x.

int x++; 

Sin embargo, no es posible en C++ en un nivel de analizador! Lo anterior podría ser analizado pero semánticamente incorrecto. El segundo ni siquiera puede ser analizado.

-1

Esto es un comportamiento indefinido y el compilador debería al menos emitir una advertencia. Intenta compilar usando g++ -ansi .... El segundo ejemplo es solo un error de sintaxis.

+0

-ansi no cambia la situación :) –

3

La variable se define desde "=", por lo que es válida y cuando está definida globalmente, se inicializa como cero, por lo que en ese caso se define el comportamiento, en otros la variable no se identificó como tal todavía está unificado (pero aumentado con 1).
Tenga en cuenta que todavía no es código muy cuerdo o útil.

0

3.3.1 Punto de declaración 1 El punto de declaración para un nombre es inmediatamente después de su completa declarador (cláusula 8) y antes de su inicializador (si existe), 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 ejemplo]

Los estados anteriores de modo y debe tener un valor indeterminado, tienes suerte con 1.

1

el código tiene dos posibilidades:

  1. Si x es una variable local, tener un comportamiento indefinido, ya que utiliza el valor de un objeto antes de que comience su vida útil.
  2. Si x tiene una vida útil estática o de subprocesos locales, se preinicializa a cero y su inicialización estática lo configurará de manera confiable en 1. Esto está bien definido.

También es posible que desee leer my answer that covers related cases, including variables of other types, and variables which are written to before their initialization is completed

Cuestiones relacionadas