tipos - Valor de retorno int implícito de la función C
todas las funciones de c++ (7)
Del estándar ''89 según se cita en el nuevo testamento:
Fluir fuera del final de una función es equivalente a un retorno sin expresión. En cualquier caso, el valor de retorno no está definido.
Esa norma generalmente expresa el comportamiento sobre el terreno de las implementaciones preexistentes.
Busqué en Google y parece que no puedo encontrar la respuesta a esta simple pregunta.
Trabajando en una base de código heredada (portada a Linux recientemente, y actualizando lentamente a un nuevo compilador) y veo una gran cantidad de
int myfunction(...)
{
// no return...
}
Sé que el retorno implícito TYPE de una función es int, pero ¿cuál es el retorno implícito? VALUE cuando no se especifica return. He probado y obtenido 0, pero eso es solo con gcc. ¿Es este compilador específico o está definido como estándar a 0?
EDITAR: 12/2017 Respuesta aceptada ajustada basada en una referencia a una versión más reciente del estándar.
Eso es simplemente un comportamiento indefinido; si no rellena el área de retorno (que, por ejemplo, generalmente es eax / rax en procesadores familiares x86 ), tendrá el último valor establecido mediante algún efecto secundario en su función.
Consulte ¿Es obligatoria una declaración de devolución para las funciones de C ++ que no devuelven el vacío? que es básicamente un duplicado de esta pregunta (excepto que está etiquetado como C ++).
Estoy seguro de que es un comportamiento indefinido para una función cuyo tipo de devolución no es void
omitir una declaración de return
. En C99 hay una excepción para main
, donde si se omite la instrucción return
, se supone que devuelve 0 implícitamente, pero esto no se aplica a ninguna otra función.
Puede funcionar en una combinación de plataforma / compilador específica, pero nunca debe confiar en tales detalles. Usar cualquier tipo de comportamiento indefinido en tu código lo hace inportable. Sin embargo, es común ver un comportamiento indefinido en el código heredado.
La declaración de devolución nunca es obligatoria al final de una función, incluso si el tipo de devolución de función no es void
. No se requiere diagnóstico y no es un comportamiento indefinido.
Ejemplo (comportamiento definido):
int foo(void)
{
}
int main()
{
foo();
}
Pero leer el valor de retorno de foo
es un comportamiento indefinido:
int bla = foo(); // undefined behavior
Del estándar C:
(C99, 6.9.1p12) "Si el} que termina una función se alcanza, y el valor de la llamada de función es utilizada por la persona que llama, el comportamiento no está definido".
La función main
es una excepción a esta regla, ya que si se llega a }
en main
, es equivalente a un return 0;
declaración.
Puede ser siempre cero en esa función, pero en la mayoría de las arquitecturas (ciertamente x86), la declaración de retorno mueve el contenido de un registro específico a un lugar específico en la pila que la persona que llama recuperará y usará como su función de retorno.
La declaración de retorno colocará la variable que se le pasó en esa ubicación para que tenga un valor diferente. Mi experiencia al no colocar una declaración de devolución específica es que es bastante aleatorio lo que se devuelve y no se puede confiar en que sea lo mismo.
Si las declaraciones return
no devuelven un valor, la función se convierte mejor y se declara como, volviendo void
:
void myfunction(...)
{
...
return;
...
}
Si hay alguna return expr;
y algunos return;
declaraciones en la función, entonces necesita decidir cuál es el mejor comportamiento y hacer que sean coherentes; siempre devuelve un valor y deja el tipo como int
o nunca devuelve un valor y cambia el tipo a void
.
Tenga en cuenta que deberá declarar funciones modificadas para devolver el void
(en un encabezado, a menos que estén, o deberían estar, static
y ocultas en un solo archivo fuente) ya que el tipo de retorno predeterminado (tipo de retorno supuesto) de int
ya no es válido.
Tal cosa es posible, pero solo bajo el supuesto de que nunca se usa el valor de retorno de la función. El estándar C11 dice en el párrafo 6.9.1:
Si se alcanza el} que termina una función y el llamador usa el valor de la llamada de función, el comportamiento no está definido.
(La versión anterior de AFAIR tenía una redacción similar)
Por lo tanto, sería una buena idea para transformar todas las funciones de ese tipo que tiene que void
funciones, por lo que ningún usuario de dicha función podría tener la tentación de utilizar el valor de retorno.