Compiler-Fehler Wieso muss bei Methode immer erst am Ende returned werden?

Bitte aktiviere JavaScript!
Hi!

Hier erstmal folgender funktionierender Code für die Berechnung des größten gemeinsamen Teils von 2 Zahlen:

Java:
package ex1;

public class Ggt {
    
    static int ggt(int x, int y) {
        int i, higher, lower;
        if(x > y) {
            higher = x;
            lower = y;
        } else {
            higher = y;
            lower = x;
        }
        
        for(i = lower; i > 0; i--) {
            if((lower % i == 0) && (higher % i == 0)) {
                break;
            }
        }
        return i;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        int num1 = 1071;
        int num2 = 1029;
        
        System.out.println("The greatest common divisor of " + num1 + " and " + num2 + " is " + ggt(num1, num2));
    }

}
Wieso darf man bei Java nicht direkt in Zeile 17 returnen - also dort 'return i', und somit aus der Methode zurück in die main-Methode zurückspringen?

Ich glaube bei C ginge das - dort halt bei Funktionen, weil wohl Funktionen bei C in java effektiv die Methoden sind?

Lg,
Zrebna
 
@mrBrown Spielverderber :)

Ich glaube bei C ginge das - dort halt bei Funktionen, weil wohl Funktionen bei C in java effektiv die Methoden sind?
Ja, in C... da darfst Du auch aus Fußpilz Mozzarella machen.

Wenn Du in C das return weglässt, dann funktioniert das max. zufällig. Bei x86 werden int-Ergebnisse per cdecl-Aufrufkonvention über das eax-Register zurückgegeben. Je nachdem, wofür dieses Register zuvor verwendet wurde, stimmt das Ergebnis - oder eben auch nicht :)
 
1.) Hier Java-Code, bei dem es nun nicht funzt sofort zu returnen, wenn man das Ergebnis hat: Siehe Zeile 19

Java:
package test;



public class Testing {

    static int ggt(int x, int y) {
        int i, higher, lower;
        if(x > y) {
            higher = x;
            lower = y;
        } else {
            higher = y;
            lower = x;
        }
       
        for(i = lower; i > 0; i--) {
            if((lower % i == 0) && (higher % i == 0)) {
                return i;
                //break;
            }
        }
        // return i;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
       
        int num1 = 1071;
        int num2 = 1029;
       
        System.out.println("The greatest common divisor of " + num1 + " and " + num2 + " is " + ggt(num1, num2));
    }

}
2.) Hier C-Code - siehe Zeile 30 - es funktioniert und sieht mir nicht nach Zufall aus:

C:
#include <stdio.h>
void swap(int* num1, int* num2);
int ggT(int* num1, int* num2);

int main() {
    int zahl1 = 1029, zahl2 = 1071;

    printf("Der groesste gemeinsame Teiler von den Zahlen %d und %d ist: %d.\n", zahl1, zahl2, ggT(&zahl1, &zahl2));

        return 0;
}

void swap(int* n1, int* n2) {
    int temp;

    temp = *n1;
    *n1 = *n2;
    *n2 = temp;
}

int ggT(int* num1, int* num2) {
    int i;

    if(*num1 > *num2) {
        swap(num1, num2);
    }

    for(i = *num1; i > 0; i--) {
        if((*num1 % i == 0) && (*num2 % i == 0)) {
            return i;
        }
    }
   // return ggT;
}
Nebenfrage:
@Zeile 6 beim C-code:
Ich deklariere und initialisiere 2 Variablen in einer Zeile.
Ist sowas bei Java nicht Konvention oder gerne gesehen? Habe das nämlich als blutiger Java-Anfänger noch nicht gesehen.
Nur Deklaration (ohne Initialisierung) in einer Zeile von mehreren Variablen habe ich dagegen gesehen.

Lg,
Zrebna
 
Also wie schon beschrieben wurde:
Der Java Compiler meckert, da du nur dann einen Wert zurück gibst, wenn in der Schleife einmal die if Bedingung wahr war.
Nun kannst Du evtl. belegen, dass dies immer der Fall sein wird, weil spätestens bei i = 1 die if-Abfrage immer zutreffen wird. Das ist toll, aber solche Gedankengänge stellt der Compiler nicht an. Also meckert er dies an. (Vollkommen zu Recht! So etwas ist ja nicht klar im Code erkenntlich und daher klar schlecht lesbarer Code!)

Der Java Compiler definiert aber in der JLS, dass sicher gestellt sein muss, dass eine Funktion einen definierten Wert zurück gibt. Also musst Du am Ende auch noch ein return haben. Also ein Java Code könnte so aussehen:
Java:
    static int ggt(int x, int y) {
        int i, higher, lower;
        if(x > y) {
            higher = x;
            lower = y;
        } else {
            higher = y;
            lower = x;
        }
      
        for(i = lower; i > 1; i--) {
            if((lower % i == 0) && (higher % i == 0)) {
                return i;
                //break;
            }
        }
        return 1; // Warum auch die 1 prüfen und dann zurück geben?
    }
Dem C-Compiler ist es komplett egal. Am Ende der Funktion ist das Ergebnis in einem Register oder an einer Stelle im Stack. Der Wert wird genommen, egal ob Du da etwas rein geschrieben hast oder nicht...
 
lustigerweise gibt C die Variable zurück, die zuletzt in der Methode beschrieben wurde, wenn diese kein "natürliches" Ende (also return) findet :D

C:
#include <stdio.h>

int
ggt (int x, int y)
{
  int i, higher, lower, rubbish=-1;
  if (x > y)
    {
      higher = x;
      lower = y;
    }
  else
    {
      higher = y;
      lower = x;
    }

  for (i = lower; i > 100; i--)
    {
      if ((lower % i == 0) && (higher % i == 0))
	{
	  return rubbish;
	}
    }
}

int
main ()
{
  printf ("Hello World\n");
  printf ("%d\n", ggt (50, 10));
  return 0;
}
 
Ich denke es wird eher die zuletzt erzeugte lokale Variable zurück geben, denn diese liegt oben auf dem Stack und C gibt nunmal immer obersten Eintrag vom Stack zurück.
 
@mihe7 hat's doch schon gesagt:
Bei x86 werden int-Ergebnisse per cdecl-Aufrufkonvention über das eax-Register zurückgegeben. Je nachdem, wofür dieses Register zuvor verwendet wurde, stimmt das Ergebnis - oder eben auch nicht :)
Was in eax drin steht, ist mehr oder weniger Zufall, und hängt nicht von der letzten Benutzung oder Deklaration ab.

Probier das testweise mal mit -O3 und x=0,y=-1 aus, dann sollte wirklich Unsinn drin stehen.
 
C:
#include<stdio.h>
int a() {
}

int b() {
    printf("Test\n");
}

int main(int argc, char *argv[]) {
    printf("a(): %d\n", a());
    printf("b(): %d\n", b());
}
Liefert bei mir mit -O1 z. B. 1 und 5, mit -O2 dagegen 0 und 5 :)
 
Ich denke es wird eher die zuletzt erzeugte lokale Variable zurück geben, denn diese liegt oben auf dem Stack und C gibt nunmal immer obersten Eintrag vom Stack zurück.
Alles klar, vielen Dank!
Interessehalber,
wie ist es den hardwaretechnisch in Java - also bei C gibt es ja das LastInFirstOut-Prinzip bzgl. Push/Pop_Stack.
Wie kann man sich das in java vorstellen?
 
Alles klar, vielen Dank!
Interessehalber,
wie ist es den hardwaretechnisch in Java - also bei C gibt es ja das LastInFirstOut-Prinzip bzgl. Push/Pop_Stack.
Wie kann man sich das in java vorstellen?
Die Antwort von @Thallius, die du zitiert hast, ist in diesem Kontext Unsinn, der Stack spielt da keine Rolle.

Aber generell funktionieren Stacks immer nach LIFO-Prinzip, das ist die Definition eines Stacks.
 
Also wenn die Rückgabe über den Stack erfolgt, dann kommt die nach meiner Erfahrung zuerst auf den Stack, dann kommt die Rücksprungadresse.
Im Anschluss baut die Funktion lokale Variablen auf dem Stack auf um dann über den Stack Pointer darauf zuzugreifen.

Am Ende wird die Funktion ihre lokalen Variablen vom Stack nehmen, dann die Rücksprungadresse + Rücksprung.

Dann ist es Aufgabe des aufrufenden Codes, das Resultat vom Stack zu nehmen.

So erinnere ich mich zumindest. Aber da dies schon länger her ist, kann ich mich evtl. irren. Und ganz wichtig: So eine Rückgabe kann auch über ein Register erfolgen wie man ja auch am Beispiel erkennen kann.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben