cast: struct ptr in void* + referenzieren



  • hi, warum kann man den struct pointer in einen void* casten und dann auch t.s2 zugreifen und referenzieren? weil der sruct pointer und die userdata d die gleiche adresse haben?

    typedef struct userdata
    {
      int *s1;
    }userdata;
    
    typedef struct temp
    {
      int *s2;
    }temp;
    
    typedef struct foo
    {
       struct userdata d;
       struct temp t;
    }foo; 
    
    void print(userdata *d)
    {
    	void *ptr = d;
    	printf("%d", *(((foo*)ptr)->t.s2));
    }
    
    int main()
    {
    	void *ptr;
    	int var1 = 3;
    	int var2 = 7;
    
    	foo *f = malloc(sizeof(foo));
    	f->d.s1 = &var1;
    	f->t.s2 = &var2;
    
    	print(&f->d);
    
    	free(f);
    
    	return 0;
    }
    


  • man "kann" es eigentlich nicht.
    sprich: du produzierst undefiniertes verhalten und das programm kann jederzeit abschmieren

    soviel zur theorie.

    da aber da die daten im speicher ja hintereinander liegen wird es in den meisten faellen klappen was du machst... aber vergiss murphey nicht: irgendwann wirds mal nen absturz geben.



  • warum ist sizeof(foo) == sizeof(userdata) + sizeof(temp)

    ist das immer so? oder liegt das am compiler oder was anderem?

    warum soll es undefiniert sein....kannst du das genauer erklären?

    n8



  • mike. schrieb:

    warum ist sizeof(foo) == sizeof(userdata) + sizeof(temp)

    ist das immer so? oder liegt das am compiler oder was anderem?

    Weil die beiden Teilobjekte ohne Padding in die Adressierungsgrenzen reinpassen. Das könnte bei neueren Systemen eventuell nicht mehr passen.

    warum soll es undefiniert sein....kannst du das genauer erklären?

    Afaik ist definiert, daß die Member in der Reihenfolge ihrer Definition im Speicher liegen - d.h. f.d hat die selbe Adresse wie f. Und aus dem Grund funktioniert dein Zeiger-Gebastel auch. Trotzdem solltest du das lieber nicht machen (in diesem Testprogramm weißt du, daß dein userdata-Objekt an erster Stelle eines foo liegt - in freier Wildbahn kannst du nicht davon ausgehen (und dann greift print() auf Daten zu, die zufällig hinter deinem Objekt liegen - BUMM).



  • Afaik ist definiert, daß die Member in der Reihenfolge ihrer Definition im Speicher liegen - d.h. f.d hat die selbe Adresse wie f

    was ist mit Padding? ...kann das auch am anfang eingefuegt werden? bisher habe ich nur folgendes gelesen: Structure padding is, adding extra bits at the end

    cu



  • Normalerweise nicht. Schließlich dient das Padding ja dazu, die "hinteren" Member auf korrekte Speicheradressen auszurichten. Und der Anfang des structs steht ja schon auf einer richtigen Adresse, also muß er nicht noch zusätzlich ausgerichtet werden.



  • Padding kann zwischen den Membern und zwischen dem letzten Member bis zur nächsten Struktur (z.B. in einem Array) auftreten. Zudem sind die Positionen (Reihenfolge) der einzelnen Member innerhalt der Struktur nicht festgelegt. Lediglich der erste Member ist sicher.

    <pedantic> rein theoretisch kann es sogar padding-Bits innerhalb eines Integers oder sowas geben </pedantic>



  • steht das alles im ansi c standard? oder wo lest ihr das nach?



  • Ja, etwas versteckt und verschlüsselt, aber ja 😉



  • TactX schrieb:

    Zudem sind die Positionen (Reihenfolge) der einzelnen Member innerhalt der Struktur nicht festgelegt.

    doch. ich glaub' das ist festgelegt.



  • net schrieb:

    TactX schrieb:

    Zudem sind die Positionen (Reihenfolge) der einzelnen Member innerhalt der Struktur nicht festgelegt.

    doch. ich glaub' das ist festgelegt.

    ja, reihenfolge muss gleich bleiben.

    aber padding bytes koennen eingefuegt werden.

    deshalb sind C strukturen auf fuer IPC und aehnliches verwendbar - man "packt" sie einfach auf 0 padding bytes (durch eine compiler anweisung) und schon kann man die strukturen problemlos in anderen programmen wieder auslesen...



  • Shade Of Mine schrieb:

    net schrieb:

    TactX schrieb:

    Zudem sind die Positionen (Reihenfolge) der einzelnen Member innerhalt der Struktur nicht festgelegt.

    doch. ich glaub' das ist festgelegt.

    ja, reihenfolge muss gleich bleiben.

    Jo, sorry. Hab's grad nachgelesen. Keine Ahnung wo ich das herhab 😕



  • TactX schrieb:

    Keine Ahnung wo ich das herhab 😕

    das ist wohl diese allgemeine unsicherheit bei vielen c-codern. wenn so vieles undefiniert ist in C, warum sollten dann ausgerechnet die reihenfolge der struct-member festgelegt sein?



  • Kann schon sein. Aber ich bin mir ziemlich sicher, dass mir das schonmal jemand gesagt hat. Naja, wayne...


Anmelden zum Antworten