2012-07-15 12 views
9

Ok, estaba jugando en Ideone y accidentalmente envié este código, sin embargo, para mi sorpresa, compiló y ejecutó un valor de 0, here.¿Por qué compila esto en Ideone?

#include <iostream> 

using namespace std; 

const int five() 
{ 
     const int i = 5; 
} 

int main() { 
     cout << five() << endl; 
     return 0; 
} 

Luego probé esto en Visual Studio, y en Codepad sin embargo ambos fracasaron debido a compilar five() no devuelve un valor, como era de esperar. Mi pregunta es, por supuesto, ¿por qué esta compilación bien en Ideone a pesar de que el código, a mi entender es incorrecto y no debe compilarse.

Respuesta

14

llano y simplemente (de C++ 11 6.6.3 "La instrucción de retorno"):

que fluye fuera del extremo de una función es equivalente a un retorno sin valor; esto da como resultado un comportamiento indefinido en una función que devuelve valor.

Por lo que el compilador puede hacer lo que quiera. Claramente, un diagnóstico es algo que preferiría de un compilador, pero hay momentos en que puede ser difícil de diagnosticar (como cuando el retorno está dentro de la lógica condicional, y el 'final' de la función nunca se alcanzaría).

Tenga en cuenta que me sale el siguiente mensaje de advertencia con GCC 4.6.1 (usando la opción Wall):

test.cpp:8:1: warning: no return statement in function returning non-void [-Wreturn-type] 

no estoy seguro de qué opciones Ideone pasa a GCC (imagino que -Wall harían lo mismo con la versión 4.3.4 que usa ideone).

Parte de la información relacionada:

En C que está bien para una función que se declara para devolver un valor que en realidad no hacerlo en ciertas circunstancias; en C solo da como resultado un comportamiento indefinido si el valor de retorno de la función es realmente usado. Pre-estándar C no siempre soportaba el tipo void, por lo que las funciones que no devolvían nada a menudo se declaraban para devolver int, explícita o implícitamente. De C99 6.9.1/12 "Definiciones de funciones": si se alcanza el } que termina una función, y el llamador utiliza el valor de la llamada de función, el comportamiento no está definido.

Además, como se menciona en un par de comentarios, que fluye desde el final de main() es tratado especialmente por C++ y C99 y posterior.

+0

¿Podría consultar el origen de la cita? –

+0

@DesmondHume: El estándar. – Xeo

+1

La única vez que está bien definido es para 'main' –

3

No devolver un valor de una función no nula es un error, pero no todo el compilador lo trata como un error, por ejemplo, GCC solo emite una advertencia cuando lo encuentra. Otros compiladores pueden ser paranoicos (y tienen razón) y no permiten compilar dicho código. Por supuesto, el comportamiento del compilador puede modificarse utilizando diferentes conmutadores y opciones.

El valor de retorno de 0 es solo un valor aleatorio; podría ser 255, -1 o cualquier otra basura, ya que hacerlo es un comportamiento indefinido (excepto para main, para el cual C99 especifica un valor de retorno 0 implícito) debe ser asumido).

3

Parece que ideone no muestra advertencias, solo muestra la salida del compilador si hubo un error. En la versión de GCC que está usando ideone (gcc 4.3), esto no es un error, es solo una advertencia.

2

El código tiene un comportamiento indefinido.Aunque lo que estás haciendo está mal, el compilador no está obligado a diagnosticarlo. El otro punto es que ideone usa lo que ahora es una versión bastante antigua de gcc. Una versión razonablemente actual de gcc (por ejemplo, 4.7) al menos le dará una advertencia de que su función está declarada para devolver un valor, pero no lo hace, pero no de forma predeterminada. Tienes que activarlo con algo como -Wall para obtener la advertencia (pero como regla general, siempre usaría al menos -Wall con gcc).

Cuestiones relacionadas