char Array aus Funktion zurückgeben



  • Hallo zusammen,

    ich habe mir gerade mal den Kopf zerbrochen wie ich am besten einen String aus meiner Verschlüsselungsfunktion zurückgebe.
    Ich wollte dabei ungern mit malloc() arbeiten.
    Meine eigentliche Funktion:

    char *EncryptString(char *input,size_t *len,char *output) {
    //verschlüssele String
    	return output;
    }
    

    Aufruf:

    char sEncryptedString[512];
    
    WriteLogFile(EncryptString("Header", strlen("Header"), sEncryptedString) ,EncryptString("String", strlen("String"), sEncryptedString));
    

    Die Frage die sich mir jetzt stellt, werden die Parameter an die Funktion WriteLogFile() nun sauber übergeben ?
    Handelt sich bei meinem Snippet um sauberen C Source oder wie gibt man sonst ein char Array aus einer Funktion sauber zurück ?



  • Du kannst einen Zeiger auf einen Speicherbereich zurückgeben, der noch nach Funktionsende existiert (im Fall von malloc), dann muss jedoch noch dafür gesorgt werden, dass dieser auch wieder freigegeben wird.
    Eine andere möglichkeit ist die rückgabe eines Zeigers auf einen (threadlokalen) statischen Speicher, wie es z.B. Funktionen wie strtok machen. Allerdings muss dieser statische Speicher groß genug sein.
    Eine ähnliche Möglichkeit ist, dass der Aufrufer der Funktion einen Zeiger auf einen Puffer übergibt. Nachteil ist auch hier, dass dieser entsprechend groß genug sein muss.



  • Du übergibst doch schon den Speicher für die Rückgabe (output).

    Da du aber beim Aufruf von WriteLogFile diesen Speicher zweimal benutzt, wird der Inhalt aber überschrieben.

    Wenn du mit C-Strings arbeitest, musst du die Länge nicht explizit mit angeben.
    Wichtiger wäre eine Angabe über die Größe von output.



  • wieso willst du überhaupt ein array zurückgeben bzw. wieso willst du nicht malloc verwenden?

    also eine möglichkeit wäre eben mit malloc und mit rückgabewert:

    char* funktion()
    {
    char *array=(char*)malloc(uswusf);
    //mach irgendwas
    return array;
    }
    

    und die andere wäre mit zeigern bzw. funktionsparametern ohne rückgabewert:

    void funktion(char *array,int laenge)
    {
    //array überschreiben
    }
    

    ist jetzt natürlich nur zur veranschaulichung und müsste entsprechend angepasst werden. 🙄 jedenfalls braucht die funktion nichts zurück zu geben, wenn du kein malloc verwendest und für dein writelogfile würde ich aus gründen einer sauberen trennung von header und daten zwei verschiedene arrays anlegen.



  • HansKlaus schrieb:

    ... jedenfalls braucht die funktion nichts zurück zu geben, wenn du kein malloc verwendest und ...

    Dann kannst du die Funktion aber nicht mehr als Parameter einer anderen Funktion aufrufen.

    z.B. hat strcpy nicht ohne Grund das Ziel als Rückgabewert.

    Das überschreiben klappt aber nicht bei Stringliteralen (zweites Beispiel)



  • macht das denn so einen unterschied, wenn man dest und src an strcpy übergibt und dann einfach dest als parameter übergibt? strcpy gibt ja auch nur dest zurück, also irgendwie spare ich mir da doch nichts, gebe aber die vielfach propagierte trennung von definition und verarbeitung auf; genauso bei den literalen. 😕



  • Hans meinte sicher das, was ich als dritten Punkt geschrieben hat. Der Benutzer gibt neben dem zu bearbeitenden string zusätzlich einen Zielpuffer an.
    Edit: Achso, jetzt weiß ich, was du meinst. Wenn die Funktion noch die übergebene Zieladresse zurückgibt, kann das auch gleich als Eingabewert verwendet werden.



  • Verwende compound literals in diesem Fall:

    enum{ESLEN=512};
    
    WriteLogFile(EncryptString("Header", strlen("Header"), (char[ESLEN]){0},EncryptString("String", strlen("String"), (char[ESLEN]){0}));
    

    Deine Variante solltest du nicht nutzen, da sie neben falschen Ergebnissen auch noch unspezifiziertes Verhalten (USB) liefert, denn die Auswertungsreihenfolge von Funktionsargumenten ist unspezifiziert, kann also bei jedem Compiler anders sein.

    Für Debug-Versionen kannst du die ausreichende Länge mit assert prüfen:

    char *EncryptString(const char *input,size_t len,char *output) {
        assert(len<ESLEN);
    ...
        return output;
    }
    


  • ja klar kann man das machen. aber man hat mir beigebracht, so spielereien wie printf("%d",a++) oder if(a++>=x) zu vermeiden, weil das den code unübersichtlich macht bzw. zu schwer auffindbaren fehlern führen kann.

    funktionen als parameter zu übergeben halte ich für ähnlich sinnvoll, auch wenn unverständlicher code gerne mal den job rettet, oder, im fall von bill gates, vor gericht als beweis gelten kann, dass irgend jemand anderes eben den code geklaut hat. 😃



  • Wutz schrieb:

    Verwende compound literals in diesem Fall:

    enum{ESLEN=512};
    
    WriteLogFile(EncryptString("Header", strlen("Header"), (char[ESLEN]){0},EncryptString("String", strlen("String"), (char[ESLEN]){0}));
    

    Ahhh...Schönes Ding. 🙂

    Ukn0wn007: ladt Dir das Draft vom aktuellen Standard runter und schau nach, was Compound literals sind.

    PS: hier noch eine fehlende Klammer ')'



  • Danek für die ausführlichen Antworten.
    Das Ziel durch die Rückgabe eines char Arrays aus einer Funktion ist halt einfach das ich Code sparen wollte.
    Sicherlich kann ich die jeweiligen Strings vorher verschlüsseln und dann die Variablen einfach an die Funktion WriteLogFile übergeben, nur leider bläht das den Code ziemlich auf.

    Habe das ganze jetzt mal angepasst und meine aufrufende Funktion wie folgt angepasst:

    typedef struct{
    	char value1[512];
    	char value2[512];
    	char value3[512];
    	char value4[512];
    	char value5[512];
    	char value6[512];
    }ENCRYPTEDSTRINGS;
    
    ENCRYPTEDSTRINGS RT;
    
    memset(&RT, 0, sizeof(ENCRYPTEDSTRINGS));
    
    WriteLogFile(EncryptString("Header", strlen("Header"), RT.value1) ,EncryptString("String", strlen("String"), RT.value2));
    

    Da dürfte doch auch nichts dagegen sprechen oder ? Speicheradressen werden ja jetzt nicht mehr wirklich überschrieben 😃



  • Ukn0wn007 schrieb:

    Das Ziel durch die Rückgabe eines char Arrays aus einer Funktion ist halt einfach das ich Code sparen wollte.

    Toll.
    Und was hast du jetzt erreicht? Mehr Code als vorher.


Log in to reply