Forum: Mikrocontroller und Digitale Elektronik Zugriff auf structs


von Mäx (Gast)


Lesenswert?

Hallo ich habe folgendes Struct:

struct telbuch
{
       char* a ;
       int* b ;
}eintrag1;


Wie fülle ich nun b? Zuweisungen wie eintrag1.b = 77; funktionieren 
nicht!

Ich steh total auf dem schlauch. Die Verwendung von structs allgem. 
(also ohne pointer) ist mir bekannt!

bitte helft mir!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

a und b sind Pointer. Solange Du die Pointer nicht initialisierst, 
zeigen sie irgendwohin.

Du musst also irgendwo und irgendwie den Speicher zur Verfügung stellen, 
auf den diese Pointer zeigen, damit Du mit Deiner Struktur sinnvolles 
anstellen kannst.


Wenn Du das erledigt hast, und Du nun Werte in den Speicher schreiben 
möchtest, auf den die Strukturelemente verweisen, musst Du wie bei einem 
normalen Pointerzugriff die Pointer dereferenzieren. Das geht mit dem 
*-Operator, oder auch, indem Du die Pointer als Array ansprichst - was 
hier aufgrund der fehlenden Information über die Größe des verwendeten 
Speichers problematisch ist.

Also:

  *(eintrag1.b) = 77;

oder

  eintrag1.b[0] = 77;

von Mäx (Gast)


Lesenswert?

1
struct telbuch
2
{
3
       char* a ;
4
       int* b ;
5
};
6
7
8
int main(int argc, char *argv[])
9
{
10
    telbuch eintrag1;
11
    *(eintrag1.b) = 77;
12
    //printf("askdfj %d    unsigned:%u \r\n",&(eintrag1.b),&(eintrag1.b));   
13
    
14
    system("PAUSE");
15
    return EXIT_SUCCESS;
16
}


wird kompiliert, schmiert unter windows jedoch ab!!!!

von Karl H. (kbuchegg)


Lesenswert?

Mäx schrieb:

> wird kompiliert, schmiert unter windows jedoch ab!!!!

logisch.
Wann immer du einen Pointer siehst, musst du dich sofort fragen: Wo 
zeigt er hin?
Ein Pointer ist eine Variable, die eine Speicheradresse enthält. Aber: 
Um einen Wert an dieser Speicheradresse abzulegen, muss es dort auch 
Speicher geben!

Eine Pointervariable selbst kümmert sich nicht um die Bereitstellung des 
Speichers. Sie enthält einfach nur die Adresse des Speichers. Das der 
Pointer auf etwas sinnvolles zeigt, ist dein Bier als Programmierer.

(UNd nein. Mit struct hat das im eigentlichen Sinne gar nichts zu tun. 
Das ist ganz einfach "Arbeiten mit Pointern")

eintrag.b ist bei dir ein Pointer. Er enthält also die Adresse im 
Speicher an der die tatsächlichen Daten zu finden sind. Aber wo ist das? 
Wo hat dieser Pointer einen Speicheradresse zugewiesen bekommen, an der 
der int tatsächlich gespeichert werden kann?

von Mäx (Gast)


Lesenswert?

ich verstehe die aussage nicht ganz. Hat mein System keinen Speicher?
die lsg von rufus hat mir nicht geholfen, mein code steht ja im letzen 
beitrag.


wenn ich pointer verwende, könnte ich zb

void foo(int *a);

und foo(&value); nutzen also die allgem. verwendung von pointern ist mir 
ja klar. nur wo ist mein problem? das Strukt soll wie oben beschrieben 
erhalten bleiben und ich will doch nur a und b befüllen bzw später auch 
auslesen

von Flo (Gast)


Lesenswert?

Konsolenprogramm?

int main()
{
  telbuch.b = NULL;      //Nullsetzen am Programmanfang, wichtig!!

  telbuch.b = new int;   //Speicherplatz reservieren

  if(telbuch.b)            //falls Zeiger in Ordnung (nicht NULL)
    *(telbuch.b) = 77;     //Speicherplatz mit Wert belegen

// irgendwie damit arbeiten




  delete telbuch.b;       //Speicherplatz wieder freigeben

  return 0;
}

müsste so funktionieren, eventuell noch bei dir anpassen.

von Karl H. (kbuchegg)


Lesenswert?

Mäx schrieb:
> ich verstehe die aussage nicht ganz. Hat mein System keinen Speicher?

Aus Sicht des C Programms nur insofern als es einen Pool von Speicher 
gibt, aus dem sich das C Programm bedienen kann. Das muss jedoch 
geordnet passieren. Du darfst nicht einfach im Speicher zugreifen wie du 
lustig bist.

Insofern hat das System keinen Speicher, ausser dem, den dein C-Programm 
angefordert hat.
Dein konkretes Programm fordert aber keinen Speicher an, ausser dem in 
dem die struct abgelegt wird. Das reicht deinem Programm aber nicht. Du 
willst ja nicht nur die struct (und damit die Pointer) als Elemente im 
Speicher haben, du willst ja auch noch Speicher benutzen können um darin 
einen int abzulegen.
Nur wo ist dieser Speicher? Wo fordert ihn dein C-Programm an?

(Sei froh, dass dir Windows hier auf die Finger klopft. Viel schlimmer 
wäre es, wenn es das nicht täte und dein Schreibversuch im Speicher 
irgendwelche anderen vitalen Daten überschreibt)

von Flo (Gast)


Lesenswert?

bei deinen foo beispiel wurde schon ein Speicherplatz reserviert, und 
zwar durch die Deklaration von "value".
Durch "&value" übergibst du die Adresse der Variable an einen Zeiger, 
der dann auf den Speicherplatz von "value" zeigt.
Bei deinem "telbuch.b" wird aber nicht auf eine schon vorhandene 
Variable gezeigt, also musst du dir Speicher besorgen.

von gerd (Gast)


Lesenswert?

Mäx schrieb:
> ich verstehe die aussage nicht ganz. Hat mein System keinen Speicher?

Wollen wir hoffen das es welchen hat... :/

> wenn ich pointer verwende, könnte ich zb
>
> void foo(int *a);
>
> und foo(&value); nutzen also die allgem. verwendung von pointern ist mir
> ja klar.

Anscheinend nicht so ganz. Was würde in deinem o.g. Bsp denn an der 
Adresse von value liegen?


> nur wo ist mein problem?

Lies noch mal den Text von Karl heinz mit Sinn und Verstand. Er hat es 
ziemlich gut auf den Punkt gebracht.

> das Strukt soll wie oben beschrieben
> erhalten bleiben und ich will doch nur a und b befüllen bzw später auch
> auslesen

Der Knackpunkt ist, womit willst du a und b befüllen?
Sinnvoll wäre die Adresse einer Speicherzelle (z.B. Position in einem 
Array), um dann über den Pointer direkt auf die Speicherzelle schreiben 
zu können (oder wie du schreibst "sie zu befüllen").

> die lsg von rufus hat mir nicht geholfen, mein code steht ja im letzen
> beitrag.

Wie gesagt - nochmal lesen und vor allem auch verstehen. ;)

- gerd

von Genmutant (Gast)


Lesenswert?

Falls du C benutzt wird dir Flos Code nicht viel helfen ;)
Hier nochmal für C:
1
struct telbuch
2
{
3
       char* a ;
4
       int* b ;
5
};
6
7
8
int main(int argc, char *argv[])
9
{
10
    telbuch eintrag1;
11
    eintrag1.b = malloc(sizeof(int));
12
    if(eintrag1.b == 0)return EXIT_FAILURE; //Fehler beim Speicheranfordern
13
    *(eintrag1.b) = 77;
14
    //printf("askdfj %d    unsigned:%u \r\n",&(eintrag1.b),&(eintrag1.b));   
15
16
    return EXIT_SUCCESS;
17
}

von Karl H. (kbuchegg)


Lesenswert?

Mäx schrieb:

> erhalten bleiben und ich will doch nur a und b befüllen bzw später auch
> auslesen

Das versteh ich schon.
Nur sind a und b keine Membervariablen in denen du einen char oder einen 
int ablegen kannst!
Das sind Pointer!
1
int main()
2
{
3
  int * ptr;
4
  int   j;
5
6
  ptr = &j;
7
8
  *ptr = 5;
9
}
baut das hier im Speicher auf
1
    ptr                     j
2
    +----+                  +----+
3
    |  o------------------->| 5  |
4
    +----+                  +----+

Das ganze geht auch mit 'anonymen Speicher'
1
int main()
2
{
3
  int * ptr;
4
5
  ptr = malloc( sizeof( int ) );
6
7
  *ptr = 8;
8
9
  free( ptr );
10
}
Das baut im Grunde dieselbe Struktur auf, nur dass der Speicher auf den 
ptr zeigt, jetzt keinen Variablennamen mehr hat und erst zur Laufzeit 
des Programms angefordert wird:
1
    ptr                     
2
    +----+            
3
    |  o-----------+
4
    +----+         |  
5
                   |
6
                   |      +----+
7
                   +----->| 8  |
8
                          +----+
Aber: Der Wert 8 wird nicht in ptr gespeichert! Er wird dort 
gespeichert, wo ptr hinzeigt.

Wichtig ist: Egal wie und warum, am Ende des Pfeiles muss es ein 
Kästchen geben, in dem ein Wert abgelegt werden kann oder aus dem 
gelesen werden kann. Der Pfeil selbst zeigt nur an, wo das ist. Aber der 
Pfeil muss auf für dein Programm reservierten Speicher zeigen 
(symbolisiert durch das Kästchen). Tut er das nicht, dann geht ein 
Schreibversuch 'in den Wald' und du beschreibst Speicher von dem kein 
Mensch weiß wo sich der im Speicher befindet. Und das darf ein 
Laufzeitsystem/Betriebssystem nach Möglichkeit nicht zulassen.

In deinem Fall hast du mit
1
    telbuch eintrag1;
dieses hier erzeugt
1
   eintrag1
2
   +----------+
3
   | a:  o---------------------->
4
   +----------+
5
   | b:  o-------------------------->
6
   +----------+
Die Pfeile zeigen irgendwo hin (weil sie ja irgendeinen Wert immer haben 
müssen). Aber wo zeigen sie hin? Am Ende der Pfeile existiert kein 
Kästchen, in dem man einen Wert ablegen könnte.

von Flo (Gast)


Lesenswert?

ups da war was, ich vergess immer die Unterschiede >_<

von Genmutant (Gast)


Lesenswert?

Und ich hab in meinem Übermut natürlich das
1
free(eintrag1.b);
vor dem letzten return vergessen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.