iammilind
A diferencia de Java, en C/C++ lo siguiente es permitió:
int* foo ()
{
if(x)
return p;
// What if control reaches here?
}
Esto a menudo provoca bloqueos y es difícil depurar problemas. ¿Por qué el estándar obligar a tener un retorno final para no-void
funciones? (Los compiladores generan un error por un error return
valor.)
¿Hay una bandera en GCC o MSVC para hacer cumplir esto? (algo como -Wunused-result
)
No está permitido (comportamiento indefinido). Sin embargo, la norma no exige un diagnóstico en este caso.
El estándar no requiere que la última declaración sea return
debido a un código como este:
while (true) {
if (condition) return 0;
}
Esto siempre devuelve 0, pero un compilador tonto no puede verlo. Tenga en cuenta que el estándar no exige compiladores inteligentes. A return
declaración después de la while
block sería un desperdicio que un compilador tonto no podría optimizar. El estándar no quiere exigir que el programador escriba código de desecho solo para satisfacer a un compilador tonto.
g++ -Wall es lo suficientemente inteligente como para emitir un diagnóstico en mi máquina.
-
“Tenga en cuenta que el estándar no exige compiladores inteligentes”. +1.
– azol
29 de julio de 2016 a las 18:22
-
Creo que un mejor ejemplo sería algo como:
int test(...) { if (...) { [compute something and return it]; } else { log_something(...); FATAL_ERROR(); }; }
. SiFATAL_ERROR()
no puede volver, entonces el final detest()
nunca se puede alcanzar, pero un compilador normalmente no tendría forma de saberlo.– Super gato
26 de julio de 2018 a las 20:28
-
Este código provoca un comportamiento indefinido si la condición es falsa (sin avance)
–MM
17 de septiembre de 2020 a las 3:00
-
@MM Este no es un código literal.
condition
representa cualquier expresión.– norte 1.8e9-dónde-está-mi-participación m.
17 de septiembre de 2020 a las 6:38
Príncipe Juan Wesley
Utilizar el -Muro bandera en CCG.
advertencia: el control llega al final de la función no nula
O más específicamente, -Tipo de retorno.
-
IIRC gcc solo lo diagnostica cuando las optimizaciones están activadas, porque utiliza el análisis de flujo de control para diagnosticarlo y eso no se ejecuta cuando no se está optimizando.
– Jan Hudec
7 de junio de 2011 a las 5:44
-
@Tj Crowder:
For C ++ , a function without return type always produces a diagnostic message, even when -Wno-return-type is specified. The only exceptions are main and functions defined in system headers
– Degcc man
página– Príncipe Juan Wesley
7 de junio de 2011 a las 5:54
-
Interesante, gcc no lo detecto con
-Wall
si lo hice enmain
ramificando enargc
. Pero hizo detectarlo si agregué una función separada y lo hice allí.main
parecería ser un caso especial (como lo es en muchos sentidos). Editar: @John: Comentarios superpuestos. 🙂–TJ Crowder
7 de junio de 2011 a las 5:56
-
@TJ
main()
no necesita contener explícitoreturn
valor; ver del sitio web de Bjarne Stroustrup www2.research.att.com/~bs/bs_faq2.html#void-main– iammilind
7 de junio de 2011 a las 6:31
-
Está definido por estándar, consulte la respuesta de Shafik aquí.
– r0n9
19 de febrero de 2014 a las 3:53
Xeo
Mi suposición: porque a veces el programador sabe más que el compilador. Con este simple ejemplo, está claro que algo está mal, pero considere un cambio de muchos valores o muchas comprobaciones en general. Tú, como codificador, saber que ciertos valores simplemente no se pasarán a la función, pero el compilador no lo hace y simplemente le indica que podría haber algo mal.
#include <iostream>
int foo(){
if(false)
return 5;
}
int main(){
int i = foo();
std::cout << i;
}
Tenga en cuenta que incluso nivel de advertencia 1 en MSVC da la siguiente advertencia:
advertencia C4715: ‘foo’: no todas las rutas de control devuelven un valor
-
“Tenga en cuenta que incluso el nivel de advertencia 1 en MSVC da la siguiente advertencia:” Eso es interesante. No entendí eso ni siquiera con el nivel 4 con VS 2005.
–TJ Crowder
7 de junio de 2011 a las 5:38
-
@TJ: Según MSDN, 2005 también debería emitir esa advertencia en el nivel 1. Vea el enlace que agregué.
– Xeo
7 de junio de 2011 a las 5:46
-
@Xeo: Fascinante. Me sale el error si agrego un
foo
funciona como el tuyo, pero no si hago exactamente lo mismo en el auto-generado_tmain
función; ejemplo. La función principal es especial (como en tantas cosas).–TJ Crowder
7 de junio de 2011 a las 5:53
-
Las advertencias de flujo de control como esta generalmente se emiten solo cuando el optimizador se ejecuta y realiza un análisis. Por lo tanto, normalmente son solo minoristas.
–Martyn Lovell
7 de junio de 2011 a las 5:53
-
@ejemplo: Eso es porque el estándar permite específicamente
main
estar sin una declaración de devolución. Si se deja fuera, el resultado es como si fuerareturn 0;
en el final.– Xeo
7 de junio de 2011 a las 6:06
florián
Puede convertir la advertencia en un error utilizando las siguientes opciones del compilador
-Wreturn-type -Werror=return-type
.
Mira esto Enlace
La respuesta obvia es: porque no es un error. Solo es un error si
x
es falso y si la persona que llama usa el valor de retorno, ninguno de los cuales necesariamente puede ser determinado por el compilador, al menos en el caso general.
En este caso particular (devolviendo un puntero), no sería demasiado difícil requerir un return
por todos los caminos; Java hace esto. En general, sin embargo, no es razonable en C++ requerir esto, ya que en C++, puede devolver tipos definidos por el usuario para los que puede ser imposible construir un valor (sin constructor predeterminado, etc.). Así que tenemos la situación en la que el programador podría no ser capaz de proporcionar un return
en una rama que sabe que no se puede tomar, y el compilador no puede determinar que la rama no se puede tomar.
La mayoría de los compiladores advertirán en tales casos, cuando pueda determinar el flujo. Sin embargo, todos los que he visto también advierten en algunos casos en los que es claramente imposible caerse del final. (Tanto g++ como VC++ advierten sobre:
int
bar( char ch )
{
switch ( ch & 0xC0 ) {
case 0x00:
case 0x40:
return 0;
case 0x80:
return -1;
case 0xC0:
return 1;
}
}
, al menos con las opciones habituales. Aunque está bastante claro que esta función nunca se cae al final).
Pedro Mortensen
Por lo que recuerdo, Visual Studio 2008 le advierte sobre una “ruta de ejecución que no tiene un valor de retorno”. Está permitido en el sentido de que “C++ no impedirá que te dispare en el pie”. Entonces debes pensar, no el compilador.
sergio
Lo que dice el estándar sobre este tipo de programación es que produce comportamiento indefinido.
El comportamiento indefinido es la alegría y la lástima de C/C++, pero también es una característica fundamental del diseño del lenguaje que permite muchas de las optimizaciones de bajo nivel que hacen de C una especie de “ensamblador de alto nivel” (en realidad, no lo es). , pero solo para darte una idea).
Entonces, al redirigir a la respuesta de John sobre el cambio para usar con GCC, para saber “por qué” el estándar no lo impide, señalaría un análisis muy interesante del comportamiento indefinido y todos sus misterios: Lo que todo programador de C debe saber sobre el comportamiento indefinido. Es una lectura muy instructiva.
El mensaje para llevar de lo siguiente es: si desea este tipo de cheques, use
-Wall
en gcc y un nivel de advertencia alto (3 o 4) en Visual Studio.–TJ Crowder
7 de junio de 2011 a las 5:58
Durante mucho tiempo he deseado una bandera del compilador que daría como resultado que todas las funciones tuvieran
throw "LOL Y U HERE??";
al final de ellos. El comportamiento no está definido, por lo que puede pasar cualquier cosa, y lanzar una excepción ciertamente califica como cualquier cosa. Solo con fines de prueba; Estaría de acuerdo con que se optimicen en el lanzamiento.–Dennis Zickefoose
7 de junio de 2011 a las 6:23
No está indefinido si
x
se declaraconst bool x = true;
.– Bo Person
7 de junio de 2011 a las 7:41
@Dennis: IIRC, ejecutar el final de una función no es UB a menos que la persona que llama intente usar el valor de retorno.
– R.. GitHub DEJA DE AYUDAR A ICE
7 de junio de 2011 a las 15:13
El estilo pobre y UB son distintos.
– R.. GitHub DEJA DE AYUDAR A ICE
7 junio 2011 a las 18:50