[c] Pointerstuff



  • Hallo!

    Ich habe ein kleines Pointerproblem(chen). Ich habe in meinem Programm ein struct, für das ich eine "create"-funktion haben möchte, da das struct ziemlich oft mit ganz speziellen Werten gefüllt werden muss.

    Nun bekomme ich vom Compiler die Warnung: "function returns address of local variable". Heisst das, das wenn die "create" - funktion beendet ist, der Pointer dann auch ungültig wird ?

    Ich habe das Problem mal ganz einfach nachgebildet und zwei Varianten geschrieben. Was ist der Unterschied zwischen den beiden, welche ist besser oder kann man das grundsätzlich anders machen ?

    Hier ein einfaches Struct:

    typedef struct{
      int a;
      int b;  
    }my_struct;
    

    build-fkt , Variante 1 (mit Compiler-Warnung)

    my_struct* build_struct1(void){
      my_struct test;
      test.a = 2;
      test.b = 393;
      return &test;  
    }
    

    build-fkt , Variante 2

    my_struct* build_struct2(void){
      my_struct* test = (my_struct*)malloc(sizeof(my_struct));
      test->a = 2;
      test->b = 222; 
      return test;
    }
    

    Zur Zeit geh ich auf nummer sicher und mache das so:

    my_struct build_struct(void){
      my_struct test;
      test.a = 2;
      test.b = 222; 
      return test;
    }
    

    Das unbequeme ist nur, das ich an aufrufender Stelle einen Pointer auf das struct brauche.



  • my_struct* build_struct1(void){ 
      my_struct test; 
      test.a = 2; 
      test.b = 393; 
      return &test;   
    }
    

    schlechte idee... test gibt es nach durchlauf von build_struct1 nicht mehr du hast also nur ne adresse von was, was es irgendwann mal gab...

    my_struct* build_struct2(void){
      my_struct* test = (my_struct*)malloc(sizeof(my_struct));
      test->a = 2;
      test->b = 222; 
      return test;
    }
    

    geht... aber unschön da der aufrufer den speicher auch wieder freigeben muss...

    my_struct build_struct(void){
      my_struct test;
      test.a = 2;
      test.b = 222; 
      return test;
    }
    

    das funktioniert weil test kopiert wird bzw. du es gleich nem anderen struct zuweist...



  • Also belasse ich es bei meiner Version.

    Jetzt hab ich noch ne Frage:

    Dieses Fragment wird anstandslos ausgeführt (Ausgabe: 123):

    char a[3] =  "123";
    char b[3];
    
    strcpy(&b,&a);
    printf("%s",b);
    

    Nur warnt mich der compiler : "passing arg 1 of `strcpy' from incompatible pointer type" .

    Was läuft falsch ? Und was ist der Unterschied zwischen "strcpy" und "memcpy" ?



  • Erstmal sollte der Aufruf von strcpy so aussehen

    strcpy(b, a);
    // bzw
    strcpy(&b[0], &a[0]);
    

    Zweitens hat das Programm so trotzdem undefiniertes Verhalten.
    Seltsam, dass dein Compiler sowas

    char a[3] =  "123";
    

    frisst. Denn "123" sind eigentlich 4 Zeichen, da du noch das abschliessenden Nullzeichen bei C-Strings beachten musst, entsprechend auch bei deinem Zielpuffer. Du kannst ja mal folgendes ausprobieren

    const char a[] = "123";
    size_t len = sizeof(a) / sizeof(char);
    

    Damit kannst du die Anzahl der Elemente von a bestimmen (ürigens solltest du Stringliterale immer const definieren, da das ändern solcher undefiniertes Verhalten ergibt).

    Der Unterschied zwischen strcpy und memcpy ist einfach der, dass strcpy nullterminierte Strings (C-Strings) kopiert, memcpy einfach nur rohe Daten. Deshalb musst du zB bei memcpy auch die Länge angeben, bei strcpy kann die Funktion die Länge durch das abschliessende Nullzeichen selbst bestimmen.


Anmelden zum Antworten