C für PICs: Strukturierte Typen



zurück zu C für PICs , C-Compiler , PIC-Prozessoren , Elektronik , Homepage

C für PICs
Grundlagen von C
Variablen
Funktionen
Operationen
Programmablaufsteuerung
Arrays und Strings
Pointer
Strukturierte Typen
PIC-spezifisches


zurück zu C für PICs


Strukturierte Typen

Wir kennen bisher einfache Typen (z.B. char, int, float) die jeweils genau einen Wert speichern können, und Arrays, die viele Werte des gleichen Typs speichern können. Oft ist es aber sinnvoll, eine Datenstruktur zu haben, die unterschiedliche Grundtypen kombiniert anstelle identischer Typen.




Structure


Eine Structur-Typ beschreibt eine Gruppe zusammengehörender Daten (Variablen), die unter einem Namen gemeinsam angesprochen werden können. Jedes Element einer solchen Structur kann einen beliebiegen Typ haben, und bekommt einen eigenen "Unter"-Namen, damit es innerhalb der Structur identifiziert werden kann. (Das entspricht in Pascal dem Record.)
Ein Structure-Typ wird wie folgt definiert:

struct dername
{
    typ element1;
    typ element2;
    typ element3;
};

Dieses Beispiel definiert den Structur-Typ mit dem Namen  "dername". Die Structur besteht aus mehreren Elementen mit den Namen element1, element2 und element3, die jeweils von einem z.Z. bekannten Typ sein müssen. Dabei darf jedes Element von einem anderen Typ sein. Man kann die Liste der Elemente beliebig verlängern.

Mit dieser Definition wurde allerdings noch keine Variable definiert, sondern nur ein neuer Typ. Von nun an kennt der Compiler den neuen Typ "dername" und es können Variablen dieses struct-Types definiert werden. Hier definiere ich nun eine Variable mit dem Namen "varname" und dem oben definierten Typ "dername".

struct dername varname;

Man kann das etwas abkürzen, indem man an die Typdefinition gleich noch eine Variablenliste oder wenigstens einen Variablennamen anhängt.

struct dername
{
    typ element1;
    typ element2;
    typ element3;
} varname;

Dieses Zusammenfassen von Daten unterschiedlicher Typen ist in der Praxis sehr praktisch, da die im Computer verwalteten Objekte aus der realen Welt oft mehrere unterschiedliche Eigenschaften haben. So lässt sich z.B. ein Auto nicht mit nur einer einfachen Variable beschreiben. Aber ein Satz von Daten unterschiedlicher Typen eignet sich sehr wohl:

struct Auto
{
    char Hersteller[30];
    char Bezeichnung[30];
    char Tueren;
    float Verbrauch;
} einauto;

Damit haben wir nun eine strukturierte Variable vom Typ "Auto" mit dem Namen "einauto". Wie kann man nun die einzelnen Elemente dieser Variable beschreiben oder auslesen? Man addressiert sie durch den Variablennamen, der um den mit einem Punkt abgetrennten Elementnamen ergänzt wird.

einauto.Hersteller = "Skoda";
einauto.Bezeichnung = "Oktavia II";
einauto.Tueren = 4;
einauto.Verbrauch = 5.1;

Besitzt man zwei Variablen von gleichen strukturierten Typ, dann kan man alle Were auf einmal übergeben:

struct Auto nocheinauto;
nocheinauto = einauto;





Union

Eine Union sieht nur auf den ersten Blick wie eine Stucture aus. Auch eine Union besteht aus mehreren Elementen, die unterschiedliche Typen haben können. Allerdings werden die Werte aller Elemente auf dem selben Speicherplatz gespeichert. Die Deklaration eines neuen union-Typs beginnt mit dem Schlüsselwort union gefolgt von neuen Namen dieses neuen Typs. Danach werden innerhalb geschweifter Klammern die Elemente der union aufgelistet. Jedes Element der Liste besteht aus dem Typ des Elements gefolgt vom Bezeicher für dieses Element. Will man gleich eine oder mehrere Variablen dieses neuen union-Typs Deklarieren, so schreibt man die Variablennamen hinter die geschweiften Klammern.

union dername
{
    typ element1;
    typ element2;
    typ element3;
} varname;

Die Größe des von einer Union belegten Speichers ist deshalb so groß wie der Speicherbedarf des größten Elements dieser Union. Beschreibt man nun ein Element einer Union mit einem Wert, dann überschreibt man automatisch die Werte aller anderen Elemente mit diesem Wert. Welchen Sinn sollte eine Union also haben? Stellen wir uns einmal vor, es wäre in einem Programm nötig, ein 16-Bit-Word in seine zwei 8-Bit Bytes zu zerlegen. Es gibt dafür mehrere programmtechnische Möglichkeiten, die eleganteste ist der Einsatz einer Union. Da natives C die Typen byte und word nicht kennt, definiere ich sie erst einmal (typedef wurde noch nicht besprochen!), dann definiere ich eine Union mit dem Namen _WORD, die aus zwei Elementen besteht. Das erste Element ist ein 16 Bit langes Word, das andere Element ist eine Folge von zwei Bytes (als Structure). Eine Variable dieser Union nenne ich Superword.

typedef unsigned char   byte;           // 8-bit
typedef unsigned int    word;           // 16-bit

union _WORD
{
    word _word;
    struct
    {
        byte LowByte;
        byte HighByte;
    };
} SuperWord;

Speichert man nun einen 16-Bit-Wert im Word-Element der Union (Superword._word) ab, dann speichert man sie gleichzeitig natürlich in den beiden Bytes des zweiten Elements der Union ab. Dort lässt sich nun auf das untere Byte (SuperWord.LowByte) und auf das obere Byte (SuperWord.HighByte) des 16-Bit-Wertes einfach zugreifen.

word a;
byte b,c;
a = 12345;
SuperWord._word = a;
b = SuperWord.LowByte;
c = SuperWord.HighByte;

Die Dezimalzahl 12345 ist als Hexadezimalzahl 0x3039. Der Programmabschnitt zerlegt die Zahl in seine zwei Bytes. Letztendlich steht in b der Wert 0x39 und in c der Wert 0x30.


--> zurück zu C für PIC-spezifischem
nach oben

zurück zu C für PICs , C-Compiler , PIC-Prozessoren , Elektronik , Homepage



Autor: sprut
erstellt: 01.10.2007
letzte Änderung: 01.10.2007