C für PICs: Programmablaufsteuerung

 

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


Programmablaufsteuerung

Ohne Anweisungen zur Programmablaufsteuerung würden in einem Programm einfach alle Anweisung nacheinander abgearbeitet werden. Es gäbe keine Möglichkeit auf veränderte Parameter zu reagieren, das Programm würde vom Start bis zu seinem Ende jedes mal genau das gleiche tun. Das wäre natürlich nicht besonders sinnvoll.
Aus diesem Grunde gibt es Anweisungen zur Programmablaufsteuerungen. Die sorgen dafür, dass bestimmte Programmabschnitte nur unter bestimmten Bedingungen ausgeführt oder auch mehrfach ausgeführt werden.



if Anweisung

Die if-Anweisung sorgt dafür, dass eine Anweisung nur unter einer bestimmten Bedingung ausgeführt wird.

if (ausdruck)
  anweisung1;

Beim Erreichen der if-Anweisung prüft der Prozessor, ob ausdruck einen von 0 verschiedenen Wert hat. Ist das der Fall (und nur dann) wird die folgende anweisung1 ausgeführt. Die gesamte if-Anweisung wird (wie jede Anweisung) durch ein Semikolon abgeschlossen. Aus diesem Grund darf hinter (ausdruck) auch kein Semikolon stehen (denn das wäre schon eine null-Anweisung), sondern erst hinter der bedingt abzuarbeitenden anweisung1.

Will man die gemeinsame Abarbeitung mehrerer Anweisungen durch eine if-Anweisung steuern, dann muss man alle diese Anweisungen durch geschweifte Klammern zu einem Anweisungsblock zusammenfassen. So ein Klammernblock wird wie eine einzelne Anweisung betrachtet. Die trennenden Semikolen innerhalb des Klammernblockes beenden deshalb die if-Anweisung nicht. Der Abschluss der if-Anweisung erfolgt mit der schließenden Klammer. (Dort ist nun kein abschließendes Semikolon nötig.)

if (ausdruck)
    {
        anweisung1;
        anweisung2;
        anweisung3;
        anweisung4;
    }



if-else Anweisung

Die if-Anweisung sorgt dafür, dass in Abhängigkeit von einer Bedingung genau eine von zwei alternativen Anweisungen ausgeführt wird.

if (ausdruck)
  anweisung1;
else
  anweisung2;

Beim Erreichen der if-Anweisung prüft der Prozessor, ob ausdruck einen von 0 verschiedenen Wert hat. Ist das der Fall, wird die folgende anweisung1 ausgeführt. Falls aber ausdruck den Wert 0 haben sollte, dann wird stattdessen anweisung2 ausgeführt.

Auch hier kann man wieder anstelle von einzelnen Anweisungen ganze Blöcke von Anweisungen verwenden, die man dann in geschweifte Klammern setzen muss.

if (ausdruck)
    {
        anweisung1;
        anweisung2;
        anweisung3;
        anweisung4;
    }
else
    {

        anweisung5;
        anweisung6;
        anweisung7;
        anweisung8;
    }




while Anweisung

Mit der while-Anweisung wird eine Schleife solange immer wieder durchlaufen, solange eine bestimmte Bedingung erfüllt ist.
Am Beginn der while-Anweisung wird geprüft, ob ausdruck den Wert 0 (false) hat. Wenn das der Fall sein sollte, dann wird der Rest der while-Anweisung übersprungen. Ist aber ausdruck von 0 verschieden, dann wird die folgende Anweisung oder der folgende Anweisungsblock abgearbeitet und danach wieder an den Anfang der while-Anweisung gesprungen. Nun wird wieder ausdruck getestet ...


while (ausdruck)
    anweisung1;



while (ausdruck)
    {
       anweisung1;
       anweisung2;
    }


Beispiel:
Das folgende ist eine Endlosschleife in der main-Funktion.

void main(void)
{
    while (1)
    {
       anweisung1;
       anweisung2;
       .....
       .....
    }
}




do-while Anweisung

Die do-while-Anweisung entspricht der while-Anweisung, allerdings wird die Schleife auf jeden Fall mindestens einmal durchlaufen.
Die Anweisungen der do-while-Schleife werden abgearbeitet, und danach wird der Wert von ausdruck geprüft. Ist dieser von 0 verschieden, dann wird wieder an den Anfang der do-while-Schleife gesprungen.

do
    {
       anweisung1;
       anweisung2;
    }
    while (ausdruck)





for Anweisung

Mit der for-Anweisung kann man eine Programmschleife festlegen, und bestimmen, wie oft sie durchlaufen werden soll.

Die for-Anweisung sieht in ihrer einfachsten Form so aus:

for (initialisierungsanweisung; ausdruck; schleifenanweisung);

In den runden Klammern stehen nacheinander drei Abschnitte.
  1. Beim Erreichen der for-Anweisung wird die initialisierungsanweisung genau einmal ausgeführt. Dabei wird normalerweise einer Schleifenzählvariable ein Startwert gegeben. diese Variable (Char oder Integer) muss vorher definiert worden sein.
  2. Nun beginnt die eigentliche Schleife. An ihrem Anfang wird geprüft, ob ausdruck den Wert 0 hat (false). Ist dass der Fall, dann wird die Schleife nicht abgearbeitet, und die for-Anweisung beendet. Andernfalls (true) wird die Schleife abgearbeitet. Mit ausdruck wird normalerweise geprüft, ob die Zählvariable einen Maximalwert überschritten hat.
  3. Die Schleife besteht im einfachsten Fall nur aus der schleifenanweisung. In der Schleifenanweisung wird normalerweise die Zählvariable incrementiert.
Das Ganze lässt sich als while-Anweisung wie folgt darstellen.

initialisierungsanweisung;
while (ausdruck)
    schleifenanweisung;

Die Schleifenanweisung der folgenden for-Anweisung wird genau 50 mal durchlaufen:

for (i=0; i<50; i++);

Solange man nur eine einzige Anweisung in der Schleife hat, und diese auch noch die Zählvariable incrementieren muss, ist so eine for-Anweisung von geringem Nutzen. Deshalb kann nach der schließenden runden Klammer (anstelle des abschließenden Semikolons) noch eine Anweisung oder ein ganzer Anweisungsblock folgen. Die Schleife besteht dann aus dieser Anweisung/Block, und der abschließenden schleifenanweisung. Zunächst erst mal ein Beispiel mit einer zusätzlichen Anweisung:

for (initialisierungsanweisung; ausdruck; schleifenanweisung)
    anweisung1;

und wie das mit einer while-Anweisung aussehen würde:

initialisierungsanweisung;
while (ausdruck)
    {
        anweisung1;
        schleifenanweisung;
    }

Nun noch ein Beispiel mit einem Anweisungsblock in geschweiften Klammern

for (initialisierungsanweisung; ausdruck; schleifenanweisung)
    {
        anweisung1;
        anweisung2;
        anweisung3;
    }

und natürlich das Äquivalent mit der while-Anweisung:

initialisierungsanweisung;
while (ausdruck)
    {
        anweisung1;
        anweisung2;
        anweisung3;
        schleifenanweisung;
    }

Nun ein etwas weniger theoretisches Beispiel. Es soll die Summe aller ganzen Zahlen von 1 bis 50 gebildet werden

char i;
integer s=0;
for (i=1; i<51; i++)

    s = s + i;





break Anweisung

Die break-Anweisung bricht die gerade laufende Schleife ab.

Beispiel:
Die folgende for-Schleife wird durch break vorzeitig beendet:

void main (void
{
    char i;
    for (i=0; i<50; i++)
    {
       ...
       ...
       if (i==10) break;
    }      
}

Die for-Schleife sollte eigentlich bis i==49 laufen, aber bei i==10 wird break abgearbeitet. Dabei wird die for-Schleife abgebrochen.
Das funktioniert auch mit while und do-while-Anweisungen.




continue Anweisung

Wird in einer Schleife eine continue-Anweisung abgearbeitet, dann werden alle folgenden Anweisungen der Schleife übersprungen, und sofort zum Test der Schleifenbedingung weitergegangen. Im Gegensatz zur break-Anweisung wird also die Schleife nicht abgebrochen, sondern nur der momentane Schleifendurchlauf.

Beispiel:
Es wird die Summe aller geraden Zahlen von 0 bis 49 berechnet:

void main (void
{
    char i;
    int  s=0;
    for (i=0; i<50; i++)
    {
       if (i%2) continue;
       s = s + i;
    }      
}




switch Anweisung

Mit der if-Anweisung kann man sich zwischen zwei Anweisungen (oder Anweisungsblöcken) wählen. Oftmals gibt es aber mehr als nur zwei Alternativen. Das ließe sich mit ineinander verschachtelten if-Anweisungen erledigen, eleganter ist aber die switch-Anweisung. Dabei wird einer von mehreren Anweisungsblöcken in Abhängigkeit vom Wert einer Variablen abgearbeitet.

Die Variable steht in Klammern hinter dem Schlüsselwort switch. Die möglichen Werte der Variable stehen in den einzelnen case-Abschnitten. Jeder case-Abschnitt enthält beliebig viele Anweisungen, die abgearbeitet werden, wenn die Variable den Wert der zugehörigen Konstante hat. Da diese Anweisungsblöcke nicht durch geschweifte Klammern begrenzt sind, werden sie durch break-Anweisungen beendet.
Falls der Wert der Variablen mit keiner der Konstanten übereinstimmt, wird der default-Abschnitt abgearbeitet. Dieser Abschnitt ist aber optional, er kann also auch fehlen.

switch (variable)
{
case konstante1:
    anweisung01;
    anweisung02;
    ...
    break;
case konstante2:
    anweisung10;
    anweisung11;
    ...
    ...
    break;
case konstante3:
    anweisung20;
    anweisung21;
    ...
    ...
    break;
default:
    anweisung30;
    anweisung31;
    ...
    ...
}





null Anweisung

Die null-Anweisung ist eine Anweisung die nichts tut. Sie wird durch ein einfaches Semikolon dargestellt. Damit ist sie ja eigentlich sinnlos, aber sie kann aus "grammatikalischen" Gründen manchmal nötig sein. Will man z.B. eine Endlosschleife bauen, aus der der Prozessor nie mehr (oder nur durch einen Interrupt) herauskommt, so kann man das eigentlich durch eine while-Schleife machen:

while (1)

Das akzeptiert der Compiler so aber  nicht, da eine while-Schleife immer eine Anweisung enthalten muss. Aber hier gibt es für eine Anweisung rein gar nichts zu tun. Da bietet sich die null-Anweisung in Form eines Semikolon als Lösung an.

while (1) ;

Das gleiche gilt z.B. für folgende for-Schleife, die die Fakultät von 30 ermittelt. Ohne das Semikolon am Ende der for-Zeile, würde der Compiler das nicht übersetzen.

float f=1;
int i;
for (i=1; i<=30, f*=i++) ;



return Anweisung

Sind  alle Anweisungen einer Funktion abgearbeitet, dann springt der Prozessor dorthin zurück, von wo die Funktion gerufen wurde. Man kann aber eine Funktion auch vorzeitig mit der return-Anweisung beenden. Das Abarbeiten eines return innerhalb einer Funktion beendet diese sofort.
Die return-Funktion bietet noch ein weiteres wichtiges Feature. Eine Funktion kann einen Rückgabewert haben. Dieser muss beim Beenden der Funktion irgendwie festgelegt werden. Das ist die Aufgabe der return-Anweisung. Auf das return-Schlüsselwort darf ein Ausdruck (z.B. eine Zahl) folgen, die bei Abarbeitung des return an die rufende Funktion zurückgegeben wird. Aus diesem Grunde kann es auch nötig sein, ein return mit folgendem Ausdruck hinter die letzte Anweisung einer Funktion zu stellen, um einen Wert zurückgeben zu können.



--> weiter zu Arrays und Strings
nach oben

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



Autor: sprut
erstellt: 01.10.2007
letzte Änderung: 23.10.2012