2011-01-10 18 views
15

Dlaczego następujący kod ma poprawne wyjście? int GGT nie ma zwrotu, ale kod i tak działa? Nie ma ustawionych zmiennych globalnych.Funkcja zwraca wartość bez instrukcji return

#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

Przekręć poziom ostrzegawczy w górę na kompilator, a powinieneś otrzymać komunikat ... –

+0

Otrzymuję komunikat ostrzegawczy, ale interesuje mnie, dlaczego działa, czy kompilator ustawia wartość zwracaną, jeśli nie ma nikogo? –

+1

możliwy duplikat funkcji [C zdefiniowanej jako int ale bez instrukcji return w treści nadal kompiluje] (http://stackoverflow.com/questions/4260048/c-function-defined-as-it-but-having-no- return-statement-in-the-body-still-compi) –

Odpowiedz

27

Dla wartości x86 wartość zwracana tej funkcji powinna znajdować się w rejestrze eax. Wszystko, co tam było, zostanie uznane za wartość zwracaną przez dzwoniącego.

Ponieważ eax służy jako rejestr zwrotny, jest często używany jako rejestr "scratch" przez calee, ponieważ nie musi być zachowany. Oznacza to, że jest bardzo prawdopodobne, że będzie używany jako dowolna zmienna lokalna. Ponieważ oba są równe na końcu, jest bardziej prawdopodobne, że poprawna wartość pozostanie w eax.

+0

gdzie jest rejestr eax? Rejestry Cpu? – Anjaneyulu

11

To nie powinno działać i na pewno nie działa na wszystkich kompilatorach i docelowym systemie operacyjnym, nawet jeśli działa na twoim.

Prawdopodobnym wyjaśnieniem jest, że funkcja zwracająca int zawsze zwraca coś, a zazwyczaj jest to zawartość rejestru. Prawdopodobnie rejestr użyty do zwracania wartości jest w twoim przypadku taki sam, jak obliczenie ostatniego wyrażenia przed powrotem z funkcji (na cele x86, oczywiście eax).

Z tego powodu kompilator optymalizacyjny wykrywający brak powrotu może całkowicie usunąć kod tej funkcji. Odtąd efekt, który widzisz (może) zniknie, gdy aktywujesz wyższe poziomy optymalizacji.

I przetestowane z gcc:

gcc bez optymalizacji: wejść 10, 20 -> 10 wynik jest

gcc -O1 wejść 10, 20 -> wynik wynosi 1

GCC -O2 wejścia 10, 20 -> wynik to 0

+1

Czy dalsi mogą wyjaśnić, w co wierzy lub nie lubi? – kriss

-3

Nie potrzebujesz zwrotu, jeśli używasz wskaźników. Zasadniczo możesz zwrócić tylko jedną wartość za pomocą instrukcji Zwrot, ale jeśli użyjesz Wskaźników, możesz zwrócić, ile chcesz.

scanf ("% d", & x1); tam dajesz funkcję adresu adresu X1, a nie X1. wskaźniki adresu szerokości prac. możesz czytać książki, aby dowiedzieć się, jak działają wskazówki.

+0

Nie sądzę, zakres zmiennych jest również ustawiony, jeśli pracuję ze wskaźnikami –

+1

Ale to nie ma nic wspólnego z pytaniem. –

+0

OH, przepraszam, przepraszam. Myślałem, że jest napisane. GGT (& x1, & x2)) i int GGT (int * x1, int * x2). Nie czytam kodu w sposób dosłowny, nie mam racji, przepraszam. :) – VakhoQ

3

Na x86 wartość zwracana jest zapisywana w rejestrze EAX, który "przypadkowo" jest również używany przez ten kompilator do przechowywania wyniku operacji arytmetycznych (lub przynajmniej odejmowania). Możesz to sprawdzić, patrząc na zespół wygenerowany przez twój kompilator. Zgadzam się z kriss - nie można zakładać, że tak będzie zawsze, więc lepiej jest wyraźnie określić wartość zwracaną.

+0

Nie myśl, że to zadziała zawsze, ale interesowało mnie, dlaczego działa w tym przypadku. Dzięki za odpowiedź! –

0

GCC w tym przypadku "zapisz" instrukcję, podczas gdy słowo "klaps" "ud2" i aplikacja ulega awarii w czasie wykonywania.

Powiązane problemy