[c] Struktur attribute ändern funktioniert nicht?

kthesun

Grünschnabel
Hallo,

Ich habe eine Struktur (hier ein Bsp mit nur einem Attribut).

Ich möchte den Wert in ein structur mit changea ädnern, allerdings ohne mystruct.a = xxx.

Also, ich möchte der Funktion einen Zeiger auf das Objekt übergeben und diese soll dann den Wert darin ändern.





Code:
struct mystruct {
 int a;
 int a2; };

int changea(struct mystruct *s, int b)
{
   printf("Wert von a: %i", *s);                      //gibt a aus!
   printf("Wert von b: %i,  *(s + sizeof(int)); //gibt b aus!
   *s = b;  //Attribut a ändern: FUNKTIONIERT NICHT! *** (Fehler kommt unten)
   *(s+sizeof(int)) = b; //Attribut b ändern;
}

}

int main()
{
   struct mystruct s;
  s.a = 5;
  printf(%i, s.a);
  changea(&s, 4);
  printf(%i, s.a);
}


Also, die Fehlermeldung heisst: incompatible types in assignment!

Kann ich mir aber absolut nicht erklären warum!

Danke!
 
Hi.
Code:
struct mystruct {
 int a;
 int a2; };

int changea(struct mystruct *s, int b)
{
   printf("Wert von a: %i", *s);                      //gibt a aus!
   printf("Wert von b: %i",  *(s + sizeof(int)); //gibt b aus!
   *s = b;  //Attribut a ändern: FUNKTIONIERT NICHT! *** (Fehler kommt unten)
   *(s+sizeof(int)) = b; //Attribut b ändern;
}

Also, die Fehlermeldung heisst: incompatible types in assignment!

Kann ich mir aber absolut nicht erklären warum!
Ähm, das liegt evtl. daran, das die Typen in der Zuweisung nicht verträglich sind?! Betrachtet man die Typen in der Zuweisung steht dort:
Code:
struct mystruct = int;
Wie soll das funktionieren? Du kannst den Compiler natürlich zwingen das zu akzeptieren:
C:
*(int*)s = b;
Dann stimmen die Typen.

Code:
 printf("Wert von b: %i,  *(s + sizeof(int)); //gibt b aus!
Das wäre allerdings Zufall wenn wirklich der Wert von b ausgegeben wird. sizeof(int) dürfte 4 sein, und wenn du 4 auf den Zeiger s addierst, schiebst du den Zeiger um 4 * sizeof(struct mystruct) Bytes weiter.

Hier wirklich b auszugeben funktioniert nicht verläßlich, denn der Compiler kann zwischen den Elementen einer Struktur auch noch Padding einfügen, so das a und b nicht unbedingt direkt hintereinander folgen.
C:
printf("Wert von b: %i",  *((int*)s + 1)); //gibt b aus!
Übrigens, gutes Minimalbeispiel. Noch besser wäre es gewesen, wenn es auch kompilierbar gewesen wäre...

Gruß
 
Zuletzt bearbeitet:
Ok, das ändern des ersten Attributs funktioniert nun schonmal...

Nur wie könnte man das zweite ändern, wenn es mit *(s + 4) nicht funktioniert?

Oder ist es nicht gewünscht Strukturen so zu verändern, sprich soll das ausschließlich mit s.b = ... gemacht werden?
 
moin, dann steh ich Grad etwas auf dem schlauch, wie ich das mit printf machsen sollte, wenn nicht mit *s+4 ! Kannst du kurz sagen wie du das b ansprechen würdest?

Ich will eigentlich garnichts damit machen, ich Spiel nur ein bisschen mit c rum, die fragen sind nur Theorie ;)
 
Man kanns natürlich auch unnötig kompliziert machen.

Wie bereits gesagt wurde sind solche pointerspielereien nicht ungefährlich weil man nicht grundsätzlich davon ausgehen kann das die beiden ints direkt hintereinander im Speicher liegen werden. Thema Alignment wurde ja bereits angesprochen.

Was spricht gegen die normale Vorgehensweise?

Code:
struct mystruct {
 int a;
 int a2;
 };

int changea(struct mystruct *s, int b)
{
   printf("Wert von a: %i", s->a); 
   printf("Wert von b: %i",  s->a2);

   s->a = b;
   s->a2 = b;
}
 
Na, genauso wie ich es auch beim printf angesprochen habe:
C:
printf("Wert von b: %i",  *((int*)s + 1)); //gibt b aus!

*((int*)s + 1) = 5;
Gruß

Hi,

Hä, und was macht das jetzt bzgl. der Speicherverwaltung besser? Also ohne die Notation zu kennen würde ich jetzt denken, man zählt zur Adresse von s, an der ein Integer steht, eben 1 Byte dazu. Oder man geht "eins weiter", was dann doch schlicht und ergreifen zu &s+4 führt (wenn Integer 4 Bytes groß ist), oder nicht?


@jsendrow: Gegen deine Lösung spricht wohl garnichts...im Gegenteil, das ist noch viel besser als das was ich mir da oben zusammengereimt habe. Aber ich hatte halt keine Ahnung, dass man mit s->Attribut auch auf dieses zugreifen kann...

Warum funktioniert s->Attribut, s*.attribut aber nicht (wenn man den Zeiger auf s hat) ?
 
Hi,

Hä, und was macht das jetzt bzgl. der Speicherverwaltung besser? Also ohne die Notation zu kennen würde ich jetzt denken, man zählt zur Adresse von s, an der ein Integer steht, eben 1 Byte dazu. Oder man geht "eins weiter", was dann doch schlicht und ergreifen zu &s+4 führt (wenn Integer 4 Bytes groß ist), oder nicht?


1. Wenn Du die Notation nicht kennst gibt es nur EINEN richtigen Weg: Lies nach wie die Notation ist. Auf Basis von Unwissenheit einfach herumraten wird dir langfristig keinen guten dienst tuen.

2. Zeigerarithmetik funktioniert abhängig vom Zeigertyp. Beispiel:

Code:
char* i;
*(i + 1) = 1;

int* j;
*(j +1) = 1;

double* k;
*(k + 1) = 1.0
Nun die Preisfrage: Um wieviele bytes wird der jeweilige Zeiger aufaddiert?

Aber ich hatte halt keine Ahnung, dass man mit s->Attribut auch auf dieses zugreifen kann...

Ähm, das gehört zu den ABSOLUTEN Grundlagen von Zeigern. Also hör auf mit komplizierten Sachen rumzuspielen, schnapp Dir ein Buch/Tutorial und lern erstmal die GRUNDLAGEN bevor Du anfängst so einen Unfug zu programmieren.
 
Zurück