|
||||||||||||||||||||||||||||||||||||||||||||||||
C definiert fuer Variable grundsätzliche Datentypen. Die Bezeichnungen für die Ganzzahlentypen ist nicht ganz unproblematisch denn die Speichergröße (und damit der Wertebereich) kann auf unterschiedlichen Prozessorsystemen unterschiedlich ausfallen. Der Datentyp ' int ' hat auf 8 und 16 Bit Prozessoren in aller Regel eine Speichergröße von 2 Byte (16 Bit), jedoch auf 32 Bit Systemen eine Speichergröße von 4 Byte (und hiermit auch einen anderen Wertebereich). Manche C-Compiler für 64 Bit CPU's verwenden für einen Integer sogar 8 Byte. Werden die Datentypen aus stdint.h verwendet, wird dem Compiler explizit mitgeteilt, welchen Speicherbedarf und welchen Wertebereich eine Variable des entsprechenden Datentyps hat. Für alle C Compiler gilt hier verbindlich, daß bspw. ein uint16_t 2 Bytes Speicher belegt (und hierbei einen entsprechenden Wertebereich besitzt), egal ob der Prozessor ein 8-, 16-, 32- oder 64-Bit Prozessor ist. Die nachfolgende Tabelle wird, wie eingangs beschrieben, beim Datentyp int und unsigned int je nach Compiler abweichen. Bei einem 32-Bit System entspricht dieser Datentyp int32_t / uint32_t, bei einem 64-Bit System int64_t / uint64_t.
In den meisten C-Implementierungen entsprechen die Datentypen float und double dem international gültigen Standard IEC 559 oder dem älteren IEEE 754. Unter dieser Annahme implementiert float das einfach lange Format, double das doppelt lange Format. Hierbei umfasst ein float 32 Bit und double 64 Bit. Doubles sind also genauer. Die Größe von long doubles ist je nach Implementierung unterschiedlich, ein long double darf aber auf keinen Fall kleiner als ein double sein. Anmerkung: 8-Bit Compiler implementieren die Datentypen im Gegensatz zu mehrbittigen Systemen für double und long double anderst. Der AVR-GCC Compiler bspw. definiert die Typen für Gleitkommazahlen alle gleich: #define
FLOAT_TYPE_SIZE 32
|
|
Programme müssen während eines Programmlaufes verwendete Daten häufig zwischenspeichern um mit ihnen später weiterrechnen zu können. Eine Variable dient grundsätzlich dazu, eine Information zu speichern. Hierfür wird eine Stelle oder ein Speicherbereich des Computers benutzt um diese Information speichern und wieder abrufen zu können. Grundsätzlich sind sämtliche Speicherstellen eines Speichers nummeriert, d.h. jede Speicherstelle wird durch eine Nummer identifiziert. Für den Programmierer wäre es sehr mühsam innerhalb eines Programms mit der Nummer des Speicherorts der die Information trägt zu arbeiten. Angenommen, es würde an Speicherstelle 2087 (das wäre die Adresse im Speicher) die Länge eines Rechtecks gespeichert werden, so müsste er, um an die Information zu gelangen, innerhalb eines Programms sagen: "Programm, lese mir den Wert an der Speicherstelle 2087 aus, damit ich die Kantenlänge des Rechtecks weiß". Würde dieses Vorgehen mit wenigen zu speichernden Informationen noch handhabbar sein, wäre es jedoch spätestens bei Verwendung von vielleicht 20, 100 oder gar 1000 Informationen gänzlich unpraktikabel. In C (und in jeder anderen Programmiersprache auch) können zu diesem Zweck den Speicherstellen Namen zugewiesen werden. Hierbei wird dem C Compiler (in aller Regel) sogar überlassen, an welcher Speicherstelle er diese Variable ablegt. Damit ein Programm mit Variablen arbeiten kann, muss im Programm festgelegt werden, dass es die zu verwendende Variable geben soll. Da es jedoch Daten unterschiedlichster Art gibt, muss zudem angegeben werden, um welche Art ( Datentyp )es sich bei der Variable handelt. Eine Variable, die die Kantenlaenge eines Rechtecks aufnehmen soll würde bspw. mit int kantenlaenge;int laenge;/* ----------------------------------------------- 001_example.c Beispiel fuer Variable 17.03.2024 ----------------------------------------------- */ #include "smallio.h" int laenge, breite, hoehe, flaeche; char ch; int main(void) { smallio_init(); while (1) { printf("\n\n\rDemo fuer Variable"); printf("\n\rQuaderberechnung\n\r"); printf("\n\rLaenge des Quaders: "); laenge= readint(); printf("\n\rBreite des Quaders: "); breite= readint(); printf("\n\rHoehe des Quaders : "); hoehe= readint(); flaeche= (2 * (laenge*breite + laenge*hoehe + breite*hoehe)); printf("\n\rQuaderoberflaeche: %d", flaeche); ch= getchar(); printf("\n\r"); } }Im Beispielsprogramm "001_example.c" werden insgesamt 4 Variablevdeklariert: laenge, breite und hoehe vom Typ Integer sowie eine Variable des Datentyps char mit dem Namen ch. Da diese Variablen nicht explizit dem Hauptprogramm "main" zugeteilt sind (und auch keiner anderen Funktion) sind diese sogenannte globale Variable. |
|
Variable besitzen eine sogenannte "Gültigkeit". Im ersten Beispiel "001_example.c" können die Variable innerhalb des gesamten Programms verwendet und auf sie zugegriffen werden. Sie haben somit eine "globale" Gültigkeit. In vielen Fällen ist dieses jedoch NICHT wünschenswert. Verwendet eine Funktion bspw. denselben Namen für eine Variable wie das Hauptprogramm, so ist nach einem Funktionsaufruf eventuell ein weiterhin benötigter Wert des Hauptprogramms verloren. Variable, die nur innerhalb einer Funktion benötigt werden sollten deshalb nur innerhalb ihrer eigenen Funktion Gültigkeit haben. Hiermit ist es möglich, in einer Funktion A dieselbe Variable wie in Funktion B oder im Hauptprogramm (main) zu verwenden ohne dass der Inhalt von einer anderen lokalen Variable überschrieben wird. In Zählschleifen finde dieses häufig eine Anwendung: /* -----------------------------------------------
002_example.c
Beispiel lokale und globale Variable
29.04.2015
----------------------------------------------- */
#include "smallio.h"
void myfunc(void)
// Funktion mit lokaler Variable i
{
int i; // lokale Variabel, nur
// gueltig innerhalb von myfunc
printf("Zaehler innerhalb von myfunc\n\r");
for (i= 0; i< 10; i++)
{
printf("%d ",i);
}
printf("\n\r\n\r");
}
int main(void)
{
int i; // Variable i ist nur im
// Hauptprogramm main gueltig
smallio_init(); // damit I/O Anweisungen funktioneren
printf("\n\r");
for (i= 0; i< 3; i++)
{
printf("%d-ter Aufruf von myfunc\n\r",i+1);
myfunc();
}
}
|
|
Eine statische Variable (static) ist grundsätzlich eine lokale Variable, die nur innerhalb einer Funktion verwendet werden kann. Im Unterschied zu einer rein lokalen Variable wird der Speicherplatz, den eine statische Variable belegt, nach Beenden der Funktion in der sie benutzt wird NICHT freigegeben. D.h. dass die Variable nach Beendigung der Funktion ihren Werteinhalt behält und bei einem späteren erneuten Aufruf der Funktion dieser Inhalt verfügbar ist. /* -----------------------------------------------
003_example.c
Beispiel statische Variable
29.04.2015
----------------------------------------------- */
#include "smallio.h"
void myfunc(void)
{
// Funktion mit statisch lokaler Variable i
static int i = 1; // statisch lokale Variabel, nur
// gueltig innerhalb von myfunc
printf("%d-ter Aufruf von myfunc\n\r", i);
i++;
}
int main(void)
{
char ch;
smallio_init(); // damit I/O Anweisungen funktioneren
printf("Demo -statische Variable-\n\r");
printf("Taste zum Zaehlen druecken\n\r");
while (1)
{
ch= getchar();
myfunc();
}
}
|
|
Wird 'volatile' bei der Definition einer Variablen benutzt, nimmt der Compiler an diesen keinerlei Optimierungen vor. Als 'volatile' definierte Variablen werden darum nie in Prozesorregister geladen. 'volatile' Variablen werden eingesetzt, wenn die Variablen zu einem beliebigen Zeitpunkt verändert werden können, die außerhalb der Ablaufkontrolle des Programms liegen. Typischerweise ist dies bei Variablen der Fall, die in einer Interruptroutine verwendet werden: volatile static char myvariable
|
|
||||||||||||||||||
Zeiger sind Variable, die anstelle von Datentypen die Adresse (reference) einer Variablen beinhalten, an der der Variableninhalt gespeichert ist. Ein Zeiger ist gewissermassen der Verweis oder der Link auf eine Variable, an der diese im Speicher zu finden ist. Definition eines Zeigers / Pointers: Datentyp *variable;Zeiger kommen vor allem immer dann zum Einsatz, wenn Variable, die aus mehr als nur einem einem Wert (Value) bestehen, bearbeitet werden sollen. Beispiel: Ein Char-Array für einen Text (String) wird definiert: char mytext[4]= "Ich";Im Speicher sieht das dann folgendermaßen aus:
Möchte man nun auf die einzelnen Elemente des Arrays zugreifen um dieses zu bearbeiten oder auszulesen hat man nun 2 Möglichkeiten: Man kann eine "Indexvariable" erstellen die dann im Stile von: char mytext[4]= "Ich";
|
|
Fasst Variable zusammen: struct
|
|
Mittels typedef können neue Datentypen definiert werden. Beispiel: typedef unsigned char byte;
// es gibt einen Datentyp "byte"
|
|
Damit Programme in einer Programmiersprache erstellt werden können, ist es notwendig, dass diese Sprache Kontrollstrukturen besitzt, die in der Lage sind, bestimmte Anweisungsblöcke nur unter bestimmten Bedingungen auszuführen oder diese bei Bedarf mehrfach zu wiederholen. Die häufigsten in C verwendeten Kontrollstrukturen sind das if-Statement zur bedingten Ausführung und die for-Schleife zur Wiederholung von zusammengefassten Anweisungen. Daneben existieren noch die while- und do{}while Schleife und das switch() case:-Statement, das aufgrund des Inhalts einer Variablen einen auszuführenden Block anspringen kann. |
|
Bedingte Programmausführung if ( ' ausdruck ' )
|
|
wiederholte Ausführung while ( 'Ausdruck' ) 'Befehl'Die Prüfung von 'Ausdruck' findet VOR der Ausführung von 'Befehl' statt, d.h. zu Anfang jedes Schleifendurchlaufs. Beispiel zu while: /* -----------------------------------------------
007_example.c
Beispiel zu while
----------------------------------------------- */
#include "smallio.h"
int main(void)
{
char mytext[] = "Mein Name ist Hase\n\r";
char index;
char ch;
char *ptr;
smallio_init();
ptr= &mytext[0]; // Zeiger erhaellt
// Adresse von mytext
// solange der Wert, auf den ptr zeigt ungleich 0
// ist, wird die Schleife wiederholt.
while (*ptr)
{
putchar(*ptr);
ptr++;
}
index= 0;;
// wiederhole so lange, wie der gelesene
// Buchstabe in mytext ungleich 'H' ist
while (mytext[index] != 'H')
{
index++;
}
printf("Buchstabe 'H' wurde gefunden an Position: %d \n\r", index);
}
|
|
do - while Schleife do 'Befehl' while ( 'Ausdruck' );Beispiel 1: /* ------------------------------------------------ 008a_example.c Beispiel zu do - while ------------------------------------------------ */ #include "smallio.h" int main(void) { unsigned int ch; smallio_init(); printf("\n\rdo - while Demo1\n\r----------------\n\r"); do { printf("\n\rEingabe Zahl 1..99 (inkl.): "); ch= readint(); } while ( !((ch> 0) && (ch <100))); printf("\n\rEingabe korrekt...\n\r"); } Beispiel 2 - Zahlensuchspiel: /* --------------------------------------------- 008b_example.c Beispiel zu do .. while ---------------------------------------------- */ #include "smallio.h" int main(void) { char suchzahl, versuche, ch; smallio_init(); printf("\n\rdo - while Demo: Zahlensuchspiel"); printf("\n\r--------------------------------\n\r"); // Zufallszahl generieren, Zaehler zaehlt so // lange immer wieder von 1..99 , bis ein Zeichen // auf der seriellen Schnittstelle eingeht und // stopt somit den Zaehler printf("\n\r generiere Zufallszahl, Taste fuer Stop\n\n\r"); do { suchzahl++; suchzahl= (suchzahl % 99)+1; printf(" **\r "); } while (!keypressed()); printf("\r "); // Zahlenanzeige loeschen ch= getchar(); versuche= 1; do { do { printf("\n\r %d", versuche); printf(". Eingabe ( 1..99 ): "); ch= readint(); } while ( !((ch> 0) && (ch <100))); if (ch == suchzahl) { printf("\n\n\r Yeaaah, Zahl wurde gefunden"); printf("\n\r Benoetigte Versuche: %d", versuche); printf("\n\n\rTaste fuer weiter...\n\r"); } else { if (ch> suchzahl) { printf("\n\rGesuchte Zahl ist kleiner !"); } else { printf("\n\rGesuchte Zahl ist groesser !"); } } versuche++; } while (ch != suchzahl); ch= getchar(); } |
|
for-Schleife for ( 'init' ;
'endebedingung' ; 'loopanweisung' )
|
|
Mehrweg-Verzweigung switch ( 'Ausdruck' ) 'Anweisung'Die optionale break-Anweisung nach den Programmanweisungen führt einen Sprung zum Ende von switch aus, d.h. zum nächsten auf das switch-Konstrukt folgenden Befehl. Der (optionale) default-Zweig wird nur dann ausgeführt, wenn alle vorherigen Vergleiche fehlgeschlagen sind. switch(Ausdruck)
|