Pointerdefinition



  • Person* p;
    Person v;
    printf("Adresse: %p\n", p);
    printf("Adresse: %p\n", &v);
    


  • %p erwartet einen void-Zeiger, andere Zeiger müssen also gecastet werden:

    printf("Adresse: %p\n", (void*)p);
    printf("Adresse: %p\n", (void*)&v);
    


  • namespace invader schrieb:

    andere Zeiger müssen also gecastet werden

    glaub' ich nicht.
    🙂



  • Ist aber so. Wenn man eine Funktion mit Prototyp aufruft, werden zwar wenn nötig andere Zeiger in void-Zeiger umgewandelt (so wie bei einer Zuweisung). Bei Funktionen mit ,... am Ende der Parameterliste (wie printf) endet diese Umwandlung aber nach den deklarierten Parametern, und für die restlichen Argumente werden nur noch die Default Argument Promotions gemacht, und die konvertieren keine Zeiger.

    gcc warnt sogar, wenn man falsche Zeiger an printf übergibt.



  • namespace invader schrieb:

    ...und für die restlichen Argumente werden nur noch die Default Argument Promotions gemacht, und die konvertieren keine Zeiger.

    als was bekommt printf denn zeiger zu sehen? als 'long' vielleicht?
    🙂



  • was sind

    Default Argument Promotions

    😕



  • +fricky schrieb:

    als was bekommt printf denn zeiger zu sehen? als 'long' vielleicht?

    Es "sieht" gar nichts. Es bekommt einen Zeiger auf Person, denkt aber es hätte einen Zeiger auf void, und es gibt Undefined Behavior.

    promotion n00b schrieb:

    was sind Default Argument Promotions

    Das ist das, was bei einem Funktionsaufruf mit Argumenten gemacht wird, bei denen nicht klar ist, was die aufgerufene Funktion erwartet (also zu was sie umgewandelt werden müssen), etwa wenn man eine Funktion ohne Funktionsprototyp aufruft, oder eben bei den überzähligen Argumenten in einer variablen Argumentenliste. Z.B. wird char zu int umgewandelt, oder float zu double. Deswegen funktioniert

    float x = 41.99;
    printf("%f\n", x);
    

    obwohl printf bei %f ein double erwartet.



  • namespace invader schrieb:

    Es bekommt einen Zeiger auf Person, denkt aber es hätte einen Zeiger auf void, und es gibt Undefined Behavior.

    stimmt, pointer auf structs und void* können (theoretisch) anders aufgebaut sein. was für eine böse falle...
    🙂



  • +fricky schrieb:

    stimmt, pointer auf structs und void* können (theoretisch) anders aufgebaut sein. was für eine böse falle...
    🙂

    Kannst du das in einem Beispiel zeigen?



  • Big Brother schrieb:

    Kannst du das in einem Beispiel zeigen?

    beispiel kenne ich nicht, aber im c-standard steht:

    A pointer to void shall have the same representation and alignment requirements as a
    pointer to a character type.39) Similarly, pointers to qualified or unqualified versions of
    compatible types shall have the same representation and alignment requirements. All
    pointers to structure types shall have the same representation and alignment requirements
    as each other. All pointers to union types shall have the same representation and
    alignment requirements as each other. Pointers to other types need not have the same
    representation or alignment requirements.
    

    ^^alle struct-pointer sind zwar kompatibel zueinander (z.b. könnten alle 3 bytes, big endian sein), aber müssen nicht notwendigerweise so aussehen wie ein void* (der z.b. theoretisch aus 6 bytes bestehen könnte). deshalb der cast im 'printf' aufruf.
    🙂



  • +fricky schrieb:

    ^^alle struct-pointer sind zwar kompatibel zueinander

    Genaugenommen auch nicht, sie haben nur die selbe Repräsentation und die selben Alignment-Anforderungen. Das heißt nicht, dass sie "kompatibel" sind.

    "For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types." (6.7.1.5)

    Wenn die structs nicht kompatibel sind (und verschiedene structs aus einer Translation Unit sind das nicht), sind also auch Pointer darauf nicht kompatibel. Das hier führt also zu undefined behavior:

    struct a;
    struct b;
    
    int main(void)
    {
        struct b *ptr;
        test(ptr); // undefined behavior!
    }
    
    int test(struct a *ptr)
    {
    }
    

    Jemand müsste mal aus Spaß eine absolut hinterhältige C-Implementierung schreiben, die zwar standardkonform ist, aber ansonsten nichts so macht wie man erwartet 🙂



  • was bedeutet alignment in verbindung mit pointern? ich kenne nur struktur-alignment.
    und was ist ein identically qualified pointer?
    mfg,
    s.n.



  • namespace invader schrieb:

    +fricky schrieb:

    ^^alle struct-pointer sind zwar kompatibel zueinander

    Genaugenommen auch nicht, sie haben nur die selbe Repräsentation und die selben Alignment-Anforderungen. Das heißt nicht, dass sie "kompatibel" sind.

    ok, verzeih meine laxe ausdrucksweise, so meinte ich das auch.
    🙂



  • standard n00b schrieb:

    was bedeutet alignment in verbindung mit pointern?

    naja, dass sie sich z.b. immer an durch x teilbare adressen befinden müssen.
    🙂



  • ok, kenne ich, erreicht man durch die #pragma_pack anweisung.
    und was ist ein qualified pointer?



  • standard n00b schrieb:

    und was ist ein qualified pointer?

    einer, der noch zusätzliche eigenschaften hat, wie const, volatile, restrict, usw. aber bezogen auf den pointer und nicht auf das, worauf er zeigt.
    🙂



  • thank you!
    🙂


Anmelden zum Antworten