2011-01-10 16 views
15

¿Por qué el siguiente código tiene una salida correcta? int GGT no tiene declaración de devolución, ¿pero el código funciona de todos modos? No hay variables globales establecidas.La función devuelve valor sin declaración de retorno

#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; 
     } 
    } 
} 
+6

Gire el nivel de advertencia directamente en su compilador, y debería recibir un mensaje ... –

+0

Recibo un mensaje de advertencia, pero estoy interesado por qué funciona, ¿el compilador establece un valor de retorno, si ¿no hay nadie? –

+1

posible duplicado de [la función C definida como int pero sin declaración de devolución en el cuerpo todavía compila] (http://stackoverflow.com/questions/4260048/c-function-defined-as-int-but-having-no- return-statement-in-the-body-still-compi) –

Respuesta

27

Para x86 al menos, el valor de retorno de esta función debe estar en eax registrar. Todo lo que estaba allí será considerado como el valor de retorno por la persona que llama.

Dado que eax se utiliza como registro de retorno, a menudo se utiliza como registro "reutilizable" por calee, porque no es necesario conservarlo. Esto significa que es muy posible que se use como cualquiera de las variables locales. Debido a que ambos son iguales al final, es más probable que el valor correcto quede en eax.

+0

donde esta registrado eax ?? ¿Registros de CPU? – Anjaneyulu

11

No debe trabajar y desde luego no funcionan en todos los compiladores y SO de destino, incluso si se trabaja en el suyo.

La explicación probable es que una función que devuelve int siempre devuelve algo, y generalmente es el contenido de un registro. Probablemente ocurra que el registro utilizado para el valor de retorno es en su caso el mismo usado 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 detecta que no hay devolución puede eliminar por completo el código de esta función. De ahora en adelante, el efecto que ve (puede) desaparecer cuando se activan niveles de optimización más altos.

I probado con gcc:

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

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

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

+1

¿Puede explicarle lo que cree o no le gusta? – kriss

-3

No necesita declaración de devolución si está utilizando punteros. En general, puede devolver solo un valor por Declaración de devolución, pero si utiliza Punteros puede devolver cuántos desea.

scanf ("% d", & x1); allí le das a funcionar una dirección de X1, no un valor de X1. punteros trabaja direcciones de ancho. puedes leer libros, para aprender cómo funciona punteros.

+0

No lo creo, el alcance de las variables también se establece si trabajo con punteros –

+1

Pero esto no tiene nada que ver con la pregunta. –

+0

OH, lo siento, lo siento. Pensé que había sido escrito. GGT (& x1, & x2)) e int GGT (int * x1, int * x2). No leo el código detalladamente, no estoy bien, lo siento. :) – VakhoQ

3

En x86, el valor de retorno se almacena en el registro EAX, que "accidentalmente" también utiliza este compilador para almacenar el resultado de las operaciones aritméticas (o al menos la resta). Puede verificar esto mirando el ensamblado generado por su compilador. Estoy de acuerdo con kriss: no puede suponer que este será siempre el caso, por lo que es mejor especificar explícitamente el valor de retorno.

+0

No creo que esto funcione siempre, pero me interesó, por qué funciona en este caso. ¡Gracias por tu respuesta! –

0

GCC pega la instrucción "ret" en ese caso, mientras que clang pega "ud2" y bloquea la aplicación en tiempo de ejecución.

Cuestiones relacionadas