Forum: Mikrocontroller und Digitale Elektronik Typedef, struct, pointer


von Ma B. (drumstick)


Lesenswert?

Hallo!

Ich habe in meinem Buch die Kapitel Pointer, Strukturen und typedef 
studiert und scheinbar nicht begriffen!

Codeausschnitt:
1
typedef enum  { eSMUImain_pwrup,       
2
                eSMUImain_stop,     
3
                eSMUImain_run,      
4
                eSMUImain_cal       
5
              }
6
        tSM_UI_main;
7
8
9
typedef enum  { eSMUIrun_stop,      
10
                eSMUIrun_runCW,     
11
                eSMUIrun_runCCW,    
12
                eSMUIrun_runCDtoCW, 
13
                eSMUIrun_runCDtoCCW,
14
              }
15
        tSM_UI_run;
16
17
18
typedef struct{ 
19
                tSM_UI_main main;   tSM_UI_main
20
                tSM_UI_run  run;    tSM_UI_run  
21
              }
22
        tSM_functions;
1
tSM_functions ms_main = {eSMUImain_pwrup, 
2
                         eSMUIrun_stop};
3
4
void functions_exe(BOOL pwrup)
5
{
6
  if(pwrup)
7
  {
8
    ms_main.main = eSMUImain_pwrup;
9
  }
10
11
  ms_main = SM_UI_exe(ms_main);
12
}

Warum wird in der if schleife
1
 ms_main.main
 und nicht nur
1
 ms_main
 geschriben und was bedeutet der Punkt dazwischen genau, ist das ein 
cast?

Weiss jemand Unterlagen, wo dies genau beschrieben wird. Ich möchte dies 
wirklich gerne begreifen!

danke und Gruss!

M.B.

von Ma B. (drumstick)


Lesenswert?

1
tSM_functions SM_UI_exe(tSM_functions ms)
2
{
3
4
  tSM_functions res = ms;
5
  //BOOL cal_OK = false;
6
  switch(ms.main)
7
  {
8
  }

Warum schreibt man in der switch nicht
1
res.main
  ??

von AVerr (Gast)


Lesenswert?

ms_main ist eine Variable vom Typ tSM_functions.
tSM_functions ist eine Struktur, besteht also aus mehreren struct 
members ( main und run ).
Wenn du nun auf den member main zugreifen willst, musst du das dem 
Compiler irgendwie mitteilen.
Genau das macht der . Operator:
In der von dir angesprochenen if-Abfrage(!) soll dem main-member von 
ms_main ein Wert zugewiesen werden, nicht der Variablen ms_main selbst ( 
denn ms_main ist ja vom Typ tSM_functions und nich vom Typ tSM_UI_main 
).

Mittels ms_main.main greift man also auf den Member main der Variable 
ms_main zu.

Sollte nur ein Pointer zu ms_main vorliegen ( also vom Typ 
tSM_functions* ), dann kann man den Operator -> benutzen ( er 
dereferenziert den Pointer und macht dann quasi das selbe wie der . 
Operator ).

von ameise (Gast)


Lesenswert?

ms_main ist ein struct. dieser besteht aus 2 anderen datentypen. der 
punkt ist der scope operator mit welchem du zugriff auf die 2 datentypen 
im struct - gennant main und run - hast.

zur zwiten frage: gute frage, macht nicht wirklich sinn.

von Karl H. (kbuchegg)


Lesenswert?

Du hast eine Struktur

struct Koordinate
{
  double x;
  double y;
};

so eine Struktur beschreibt ein großes Ganzes. Wenn also von einer 
Kooridinate die Rede ist, dann ist das komplette Objekt gemeint: Eine 
vollständige Koordinate. So eine Koordinaten (die zb einen Punkt 
beschreibt) hat aber eine Feinstruktur: sie besteht aus einem X-Wert und 
aus einem Y-Wert.

Andere Beispiele:
* Ein komplettes Datum besteht aus einem Tag, einem Monat und einem 
Jahr. Reden wir von einem Datum an sich (zb "Wann wurdest du geboren?") 
dann ist damit dieser vollständige Datensatz gemeint.

* Du selbst hast einen Namen. In unserem Kulturkreis ist es üblich, dass 
ein kompletter Name aus einem Vornamen und einem Familiennamen besteht.

* ...

Diese Zusammenfassung von mehreren Informationen zu einem größeren 
Ganzen wird in den meisten Programmiersprachen mit einer Struktur 
gemacht. Die Struktur ist sozusagen ein kleines Kästchen, in der die 
Einzelteile fein säuberlich in einzelnen Schubladen existieren. Du 
kannst das Kästchen als ganzes nehmen, du kannst aber auch nur eine 
Schublade davon nehmen wollen.

struct Datum
{
  int Tag;
  int Monat;
  int Jahr;
};

struct Name
{
  char Vorname[40];
  char Familienname[40];
};



  struct Datum Geburtstag;

Die Variable Geburtstag ist nach der Blaupause 'struct Datum' aufgebaut. 
Bei einem Geburtstag handelt es sich also um ein Objekt, welche in 
seiner Feinstruktur einen Tag, ein Monat und ein Jahr besitzt, weil die 
Blaupause 'struct Datum' das so vorsieht.

Jetzt kommt es aber natürlich auch in einer Programmiersprache vor, dass 
man sich einmal auf das Ganze bezieht

  printDate( Geburtstag );

weil eben die Funktion printDate ein komplettes Datum benötigt um es 
auszudrucken, oder eben manchmal auch nur auf einen Teil dieses Ganzen.

   Geburtstag.Tag = 22;

(Der Tag deiner Geburt war der 22-te. Damit ist nichts über Monat oder 
Jahr ausgesagt. Es geht nur um den Tag, also die Komponente eines 
kompletten Datums, welches den Tag beschreibt).

Bezieht man sich auf einen Teil einer Struktur, dann schreibt man diesen 
Teil nach dem Punkt auf.
Geburtstag ist ein komplettes Datum. Und der Monat-Teil dieses 
kompletten Datums ist  Geburtstag.Monat

> Warum wird in der if schleife
'if' bildet keine Schleife. Das Wesen einer Schleife besteht darin, dass 
etwas potentiell wiederholt wird. Bei einem if wird nichts wiederholt. 
if regelt die Auswahl von 2 Alternativen. Entweder - oder. Das ist aber 
keine Schleife.

von Ma B. (drumstick)


Lesenswert?

ms_main ist ein struct vom Typ tSM_functions kann auf die Member 
main(vom Typ tSM_UI_main) und run(vom Typ(tSM_UI_run) zugreifen!? 
tSM_UI_main ist eine Variable die mehrere Zustände haben kann(Enum)??

Mit dem typedef mach ich eine Variable zu einem Typ??



if() ist keine Schleife, denn schleifen wiederholen sich. (while(), 
for())

von Bernhard R. (barnyhh)


Lesenswert?

M. B. schrieb:
> Weiss jemand Unterlagen, wo dies genau beschrieben wird. Ich möchte dies
> wirklich gerne begreifen!

Jedes C-Lehrbuch! Lesen bildet.

von Karl H. (kbuchegg)


Lesenswert?

M. B. schrieb:

> Mit dem typedef mach ich eine Variable zu einem Typ??

Welches Buch benutzt du?


Nein. Mit einem typedef erzeugst du einen anderen Namen für einen 
Datentypen.
Formal gestaltet sich das so, dass man eine Variablendefinition 
hinschreibt. Zb

  int  MyInt;

und ein typedef davorstellt

typedef int MyInt;

Dies erzeugt einen neuen Datentypnamen namens 'MyInt' (der Name wird 
also von dort geholt, wo normalerweise der Name der Variable steht) der 
identisch ist mit dem Datentyp aus der Variablendefinition (hier int).

Anderes Beispiel

   char  Folge[40];

erzeugt ein Array von 40 char. Der Name der Variablen ist 'Folge' und 
ihr Datentyp ist "Array von 40 char".

Folglich erzeugt

   typedef char Folge[40];

einen neuen Datentyp namens 'Folge', der ein anderer Name für den 
Datentyp 'Array von 40 char' ist.

Definiere ich daher eine richtige Variable

   Folge  Vorname;

dann ist die Variable 'Vorname' vom Datentyp 'Folge'. Und da 'Folge' nur 
ein anderer Name für den Datentyp 'Array von 40 char' ist, folgt daraus, 
dass Vorname ein 'Array von 40 char ist'.

Man spart sich damit unter umständen einiges an Tippaufwand und es ist 
auch oft leichter die Dinge auf gleich zu halten

Hier
1
struct Name
2
{
3
  char Vorname[40];
4
  char Familienname[40];
5
};

wurde in einer Struktur explizit festgelegt, dass die beiden Namen 40 
Zeichen haben sollen.

Hier
1
typedef char String[40];
2
3
struct Name
4
{
5
  String Vorname;
6
  String Familienname;
7
};

wurde dieses Wissen an einer Stelle zentralisiert.

von Karl H. (kbuchegg)


Lesenswert?

Jetzt geht die Sache aber noch weiter.

Wir hatten
1
struct Datum
2
{
3
  int Tag;
4
  int Monat;
5
  int Jahr;
6
};
welches ein komplettes Datum beschreibt. Soweit, so gut.

In C ist aber der Name einer Struktur ('Datum') nicht automatisch ein 
neuer Datentyp. Der korrekte Datentyp lautet 'struct Datum'. Ergo muss 
man überall, wo man ein Datum benötigt auch immer den korrekten Datentyp 
'struct Datum' anführen ....
1
int main()
2
{
3
  struct Datum Geburtstag;
4
  struct Datum Hochzeitstag;
5
6
  printDate( Geburtstag );
7
  printDate( Hochzeitstag );
8
}
9
10
void printDate( struct Datum wann )
11
{
12
  printf( "%d %d %d", wann.Tag, wann.Monat, wann.Jahr );
13
}
... und bei entsprechend häufiger Verwendung des Datentyps wird das 
schnell lästig.

Man kann sich daher in C für 'struct Datum' nach bereits bekanntem 
Muster einen neuen, in der Schreibweise kürzeren, Namen eines neuen 
Datentyps erzeugen: Nimm eine Variablendefinition, schreib 'typedef' 
davor und der Name an der Position der Variablen wird zum Namen eines 
neuen Datentyps
1
struct Datum
2
{
3
  int Tag;
4
  int Monat;
5
  int Jahr;
6
};
7
8
typedef struct Datum Date;

damit ist 'Date' zu einem vollwertigen Datentypnamen definiert worden 
und kann dann auch so benutzt werden:
1
int main()
2
{
3
  Date Geburtstag;
4
  Date Hochzeitstag;
5
6
  printDate( Geburtstag );
7
  printDate( Hochzeitstag );
8
}
9
10
void printDate( Date wann )
11
{
12
  printf( "%d %d %d", wann.Tag, wann.Monat, wann.Jahr );
13
}


Allerdings ist es in C auch möglich, bei der Definition einer Struktur 
auch gleich eine (oder mehrere) Variablen dieses Strukturtyps zu 
vereinbaren:
1
struct Datum
2
{
3
  int Tag;
4
  int Monat;
5
  int Jahr;
6
} Geburtstag, Hochzeitstag;

das definiert in einem Aufwasch gleichzeitig wie die Struktur aussieht 
und auch noch gleich 2 Variablen von diesem Typ.

Variablendefinition ... da war doch was?

Genau. Nimm eine Variablendefinition, schreib ein 'typedef' davor und 
der Variablenname wird zum Namen eines neuen Datentyps, der dafür steht.
1
typedef struct Datum
2
{
3
  int Tag;
4
  int Monat;
5
  int Jahr;
6
} Date;

ist also nichts anderes als eine verkürzte Schreibweise für
1
struct Datum
2
{
3
  int Tag;
4
  int Monat;
5
  int Jahr;
6
};
7
8
typedef struct Datum Date;

von Ma B. (drumstick)


Lesenswert?

1
tSM_functions ms_main = {eSMUImain_pwrup, 
2
                         eSMUIrun_stop};

ms_main ist eine Strukturvariable des Typs tSM_functions mit den membern 
eSMUImain_pwrup und eSMUIrun_stop ??

von Karl H. (kbuchegg)


Lesenswert?

Nein.

Eine Variable kann bei ihrer Definition auch gleich mit Werten 
initialisiert werden.

  int i = 5;
  int k = 8;

oder aber auch

  struct Datum Geburtstag = { 24, 12, 2011 };


Irgendwie hab ich das Gefühl du liest dein Buch nur. Grundsätzlich ist 
es nicht schlecht wenn du liest. Du musst aber auch die Übungen machen 
und selber programmierern, damit du die Dinge erkennst, wenn du sie im 
Code siehst. Es bringt nichts, wenn man zu schnell die einzelnen Kapitel 
verschlingt oder nur liest.
1
tSM_functions ms_main = {eSMUImain_pwrup, 
2
                         eSMUIrun_stop};
> ms_main ist eine Strukturvariable des Typs tSM_functions

Soweit noch richti

> mit den membern
> eSMUImain_pwrup und eSMUIrun_stop ??

Wie können das Member sein, wenn da keine Datentypen stehen? Die 
'Member' von ms_main sind 'main' und 'run' und zwar deshalb weil hier
1
typedef struct{ 
2
  tSM_UI_main main;
3
  tSM_UI_run  run;
4
}
5
 tSM_functions;

beschrieben wurde, wie der Feinaufbau einer Variablen ist, die vom Typ 
'tSM_functions' ist. Eine tSM_functions Struktur besteht aus 2 
Komponenten (eben den Membern): die eine nennt sich 'main' und ist vom 
Typ 'tSM_UI_main', die andere nennt sich 'run' und ist vom Datentyp 
'tSM_UI_run'.

ms_main hat also die Member 'main' und 'run'. Und diese Member werden 
mit den Werten 'eSMUImain_pwrup' und 'eSMUIrun_stop' initalisiert.

von Ma B. (drumstick)


Lesenswert?

Ah, member main wird mit eSMUImain_pwrup und member run mit 
eSMUIrun_stop initalisiert!!

Ganz langsam blick ich immer mehr durch! Vielen Dank! Ja, es stimmt 
schon. Ich bin nicht zu faul zum lesen, im Gegenteil. Aber ich muss mehr 
Übungen machen!

Grüsse!

von utrtruurr (Gast)


Lesenswert?

mit zeiger auf jene strukturen wird anders zugegriffen
1
tSM_functions SM_UI_exe(tSM_functions *ms)
2
{
3
  switch(ms->main)
4
  {
5
  }
6
}

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.