struct tm Zurückgeben aus Funktion



  • Hallo Leute,

    ich bin mir nicht ganz klar darüber, wie ich eine tm Zeitstruct zurückgeben soll, muss.

    folgendes:

    struct tm *stopp(void){
    
    	time_t start, end, gesamt;
    	struct tm *buffer;
    	char key[10];
    
    	//system("cls");
    	puts("Start Time with Any Input");
    	fgets(key, 10, stdin);
    	puts("\t:::::: RUN ::::::::::::\n\t  stop with any input\n");
    	time(&start);   //start Stopper
    	fgets(key, 10, stdin);
    	time(&end);    // stop STopper
    	gesamt=end-start;
    	buffer=localtime(&gesamt);
    
    	return buffer;
    
    }
    

    Im Aufruf :

    struct tm *test;
    
    test=stopp();
    
    printf("%d min %d sec", test->tm_min, test->tm_sec);
    

    Also das funktioniert bei mir schon, aber müsste ich nicht eigentlich mal Speicher für den Pointer erzeugen? Bin mir nicht wirklich sicher ob ich das richtig zurück gebe, habe auch evtl. etwas zuuu viel darüber gelesen heute....


  • Mod

    unsure123 schrieb:

    Also das funktioniert bei mir schon, aber müsste ich nicht eigentlich mal Speicher für den Pointer erzeugen? Bin mir nicht wirklich sicher ob ich das richtig zurück gebe, habe auch evtl. etwas zuuu viel darüber gelesen heute....

    Gut mitgedacht 👍 , aber die Dokumentation nicht gelesen 👎 . localtime gibt einen Zeiger auf irgendein internes struct tm zurück.

    Ja, das ist natürlich hochgradig threadunsicher und man muss unbedingt aufpassen, weil Folgeaufrufe von localtime und(!) gmtime diese internen Daten verändern können. Aber das ist eben die C-Standardbibliothek, die ist nicht unbedingt nach modernstem objektorientierten Stil designt.



  • Hm... aber prinzipell kann ich es so lassen, ja?

    jetzt von struct tm abgesehen würde folgendes falsch sein :

    struct XY{....}

    struct XY *foo(void){

    struct XY temp;
    temp....=2;
    temp....=3;

    return temp; // Verliert beim Verlassen der Funktion eigentlich alles
    }

    main:
    struct XY *test2;

    test2=foo(); //könnte irgendwas ergeben oder?



  • Das ist falsch, da der Rückgabewert der Funktion ein Zeiger sein soll.
    Beim return gibst du aber das Objekt selber an.

    Warum nimmst du den Zeiger?
    In C kann man auch ganze structs zuweisen und auch zurück geben.

    struct XY foo(void){
    
    struct XY temp;
      temp....=2;
      temp....=3;
    
    return temp;
    }
    


  • Warum nimmst du den Zeiger?

    Das hat sich irgendwie so ergeben, und jetzt würde ich gerne rausfinden wie man es mit Zeiger richtig macht.

    Das ist falsch, da der Rückgabewert der Funktion ein Zeiger sein soll.
    Beim return gibst du aber das Objekt selber an.

    Bei der Struct TM Sache oder bei dem anderen Beispiel?

    zu

    Beim return gibst du aber das Objekt selber an.

    char *f1( char *dest){
    
    strcpy(dest, "blabla");
    return dest;
    }
    

    Ist jetzt keine Struct, aber da gebe ich ja auch nen Zeiger zurück, auch wenn es nicht sein müsste...

    In meinen Beispielen die ich so habe, wird meistens mit nem Zeiger auf Struct TM gearbeitet, darum wrüde ich gerne einen Zeiger darauf zurück geben.

    Ich hab´s aber soweit richtig verstanden, das das falsch ist ja?
    FALSCH:

    struct XY{....}
    
    struct XY *foo(void){
    
    struct XY temp;
    temp....=2;
    temp....=3;
    
    return temp; // Verliert beim Verlassen der Funktion eigentlich alles
    }
    
    main:
    struct XY *test2;
    
    test2=foo(); //könnte irgendwas ergeben oder?
    

    Somit brächte ich jetzt mal ein Beispiel wie es mit ner normalen STruct richtig geht, und wie mit dieser sch*** struct TM



  • Ein Zeiger ist ein Verweis auf den Beginn einen Datenbereiches.
    Die Sache steht und fällt damit, was zum Zeitpunkt der Dereferenzierung (d.h. also der Auswertung) passiert;
    dabei ist es irrelevant, welchen Basistyp der Zeiger hat (struct,char,int,...).

    localtime liefert einen Zeiger auf einen (bibliotheksinternen) Speicher zurück,
    du sollst dafür auch kein 'free' aufrufen.

    struct tm *meinefkt()
    {
      struct tm *p = localtime(...);
      return p;
    }
    int main()
    {
      struct tm *p = meinefkt(); /* OK */
      struct tm st;
      st = *meinefkt();  /* OK; struct-Inhalt wird kopiert */
      p = &st; /* OK */
      st = *p; /* OK */
    }
    
    ...
    struct tm *meinefkt1()
    {
      struct tm st = *localtime(...);
      return &st; /* falsch! */
    }
    


  • beginner88888 schrieb:

    Ist jetzt keine Struct, aber da gebe ich ja auch nen Zeiger zurück, auch wenn es nicht sein müsste...

    structs sind keine Arrays.
    Von daher sind deine Annahmen falsch.

    beginner88888 schrieb:

    Somit brächte ich jetzt mal ein Beispiel wie es mit ner normalen STruct richtig geht, und wie mit dieser sch*** struct TM

    Das habe ich doch schon gezeigt.
    Der Unterschied liegt in Zeile 1 und Zeile 3
    Mein Beispiel

    struct XY foo(void){  // Rückgabe einer struct
    
    struct XY temp;
      temp....=2;
      temp....=3;
    
    return temp;  // Rückgabe einer struct
    }
    

    Dein Beispiel

    struct XY{....}
    
    struct XY *foo(void){  // Rückgabe eines Zeigers auf eine struct
    
    struct XY temp;
    temp....=2;
    temp....=3;
    
    return temp; // Rückgabe einer struct. Darum ist dein Beispiel falsch.
    }
    

    So macht es localtime (ungefähr)

    struct XY{....}
    
    struct XY *foo(void){  // Rückgabe eines Zeigers auf eine struct
    
    static struct XY temp;  // Achte auf das static
    temp....=2;
    temp....=3;
    
    return &temp; // Rückgabe eines Zeigers auf eine struct.
    }
    

    Du bekomst aber bei jedem Aufruf die gleiche Adresse geliefert. Auch wenn du die in Unterschiedlichen Pointern ablegst, zeigen die alle auf dieselbe struct und somit auf dieselben Daten



  • Ist jetzt keine Struct, aber da gebe ich ja auch nen Zeiger zurück, auch wenn es nicht sein müsste...

    structs sind keine Arrays.
    Von daher sind deine Annahmen falsch.

    Aber bei der Char* Rückgabe , also für Strings... Normal müsste ich doch da gar nichts zurück geben, warum also überhaupt das return? Also hier:

    char *f1( char *dest){
    
    strcpy(dest, "blabla");
    return dest;
    }
    


  • Müssen musst du das nicht.

    Du kannst so Funktionen verketten.

    (Unsinniges Beispiel, so wie deins 🙂 )

    char ziel[100];
    
    puts(f1(ziel));
    size_t l = strlen(f1(ziel));
    

    Das ist z.B. auch der Grund für die Rückgabewerte von strcpy oder strcat.



  • Dann wäre folgendes auch richtig, aber "sinnlos":

    char *test(char *dest){
    
      char buffer[50]; 
      strcpy(buffer, "sinnlos");
      strpy(dest, buffer);    // hier wäre "sinnlos" schon an den Aufrufer "zurückgegeben"
      return buffer  // ??? Käse ... müsste wenn dann  "return dest" sein, oder hald gar nichts?
    


  • Da buffer am Ende der Funktion nicht mehr existiert, ist es nicht sinnvoll den Zeiger darauf zurückzugeben.

    Der Compiler übersetzt das1 und gibt, wenn er richtig eingestellt ist, auch eine Warnung aus.

    1Er wird wegen des fehlenden c beim zweiten strcpy meckern. Etwas von "Implizite Funktionsdeklaration". Dann meldet der Linker den Fehler (nicht aufgelöstes Symbol).



  • Sehe ich es richtig, das bei
    "return dest" ja eine Adresse zurückgegeben wird, die nach beenden der Funtkion auch noch besteht(da sie ja in der FUnktion nur eine Referenz ist), und somit return dest funktioniert?



  • Ja, siehst du richtig.



  • Ja, siehst du richtig.

    😃 😃 YEAH 😃 😃 😉



  • Danke an alle für die hilfreichen Antworten!

    DirkB, Wutz & SeppJ... Ihr seid meine Helden 👍


Anmelden zum Antworten