Typedef, struct, pointer

OP #2503757
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.
Gast #2503774
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 ).
Gast #2503784
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.
#2503787
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.
OP #2503805
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())
#2503824
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.
#2503853
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;
#2503870
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren