La función devuelve valor sin declaración de devolución

Resuelto Pascal Bayer asked hace 13 años • 6 respuestas

¿Por qué el siguiente código tiene un resultado correcto? int GGT no tiene declaración de devolución, pero ¿el código funciona de todos modos? No hay variables globales establecidas.

#include <stdio.h>
#include <stdlib.h>

int GGT(int, int);

void main() {
    int x1, x2;
    printf("Bitte geben Sie zwei Zahlen ein: \n");
    scanf("%d", &x1);
    scanf("%d", &x2);
    printf("GGT ist: %d\n", GGT(x1, x2));
    system("Pause");
}

int GGT(int x1, int x2) {
    while(x1 != x2) {
        if(x1 > x2) {
            /*return*/ x1 = x1 - x2;
        }
        else {
            /*return*/ x2 = x2 - x1;
        }
    }
}
Pascal Bayer avatar Jan 10 '11 15:01 Pascal Bayer
Aceptado

Al menos para x86, el valor de retorno de esta función debe estar en eaxel registro. Todo lo que haya allí será considerado como el valor de retorno por la persona que llama.

Debido a eaxque se utiliza como registro de retorno, el destinatario a menudo lo utiliza como registro "sustitutivo", porque no es necesario conservarlo. Esto significa que es muy posible que se utilice como cualquiera de las variables locales. Debido a que ambos son iguales al final, es más probable que se deje el valor correcto eax.

ruslik avatar Jan 10 '2011 08:01 ruslik

No debería funcionar y ciertamente no funciona en todos los compiladores y sistemas operativos de destino, incluso si funciona en el suyo.

La explicación probable es que una función que devuelve int siempre devuelve algo y, por lo general, es el contenido de un registro. Probablemente suceda que el registro utilizado para el valor de retorno sea, en su caso, el mismo utilizado para calcular la última expresión antes de regresar de la función (en objetivos x86, ciertamente eax).

Dicho esto, un compilador de optimización que detecte que no hay retorno puede eliminar completamente el código de esta función. De ahora en adelante, el efecto que ve (puede) desaparecer al activar niveles de optimización más altos.

Lo probé con gcc:

gcc sin optimización: entradas 10, 20 -> el resultado es 10

gcc -O1 entradas 10, 20 -> el resultado es 1

gcc -O2 entradas 10, 20 -> el resultado es 0

kriss avatar Jan 10 '2011 08:01 kriss

Si una función está definida para devolver un valor pero no lo hace, y la función que llama intenta utilizar el valor de retorno, se invoca un comportamiento indefinido .

Esto se detalla en la sección 6.9.1p12 del estándar C :

Si }se alcanza el valor que termina una función y la persona que llama utiliza el valor de la llamada a la función, el comportamiento no está definido.

En este caso, tuvo "suerte" de que el programa pareciera funcionar correctamente, pero no hay garantía de ello. Si hubiera compilado con diferentes configuraciones de optimización o con un compilador completamente diferente, podría terminar con resultados diferentes.

Entonces, la moraleja de la historia: si la función dice que devuelve un valor, siempre devuelve un valor.

dbush avatar Oct 17 '2019 03:10 dbush