Präprozessor: Deklarartion eines Listenindex aus Verwendung ermitteln.

21/10/2007 - 18:56 von Paul Rosen | Report spam
Hallo,

ich bin in C, insbesondere bei dessen Pràprozessor noch etwas wackelig
auf den Beinen und es stellt sich folgendes Problem:

In einem Microcontroller laüft ein Programm für gewöhnlich nach der
Intitialisierungsphase in einer unendlichen Schleife ab, wenn diese
nicht durch Interrupts unterbrochen wird. In dieser Schleife wird
mehrfach eine gleiche Funktion mit nur einem Argument aufgerufen.
Dieses Argument wird in der Funktion als Index zur Adressierung eines
eindimensionalen Feldes verwendet, das global definiert wurde und im
Gesamtprogramm weiterverwendet wird. Die Funktion wird maximal einmal
mit dem gleichen Argument/Index aufgerufen.

Wenn man mit der Programmierarbeit beginnt, steht noch nicht fest, wie
oft diese Funktion benötigt wird, wenn das Programm fertig ist, schon.
Fest steht ferner, dass das Unterprogramm auf vielen Microontrollern
mit unterschiedlichen Aufgaben und Firmware extensiv zum Einsatz
kommt. Von Controller zu Controller àndert sich dabei die Anzahl der
Funktionsaufrufe und damit der Umfang des Feldes. Man könnte das
Problem des variierenden Feldumfanges mit einer zeigerverketteten
Liste erschlagen. Letztere geht aber davon aus, dass sich die
Listenlànge auch noch zur Runtime àndert. Das ist aber hier nicht der
Fall. Der Listenumfang liegt schon zur Pràprozessorzeit fest. Somit
würde die zeigerverkettete Liste zur Runtime Ressourcen forden, die in
diesem Falle nicht nötig wàren. Und die sind auf einem Controller
bekanntermassen immer noch nicht im Überfluss vorhanden und zudem
stromfressend. Die Nutzung der Array Funktion, und damit eine
Behandlung des Problems zur Pràprozessorzeit würde also Ressourcen
sparen. Dies insbesondere deswegen, weil der (Signal)contoller diese
Art der Behandlung in Hardware gegossen unterstützt. Am Ende des
Postings unten habe ich dies genauer erklàrt.

Nun steht die Anzahl der Funktionsaufrufe und damit auch der Umfang
des eindimensionalen Feldes schon zum Pràprozessorzeitpunkt fest.
Daher die Frage: Gibt es eine Möglichkeit, schon im Pràprozessor, die
verwendeten Indexe abzutasten und daraus den zu definierenden Index
des eindimensionalen Feldes zu bestimmmen. Möglicherweise kann der
Pràprozessor auch noch durch Löschen entstandene Lücken eliminieren,
indem er die Aufrufe neu durchnumeriert. Zum Beispiel wird eine
verwendete Indexliste {7, 3, 9} zu {0, 1, 2} optimiert. Wichtig ist
dabei natürlich, dass alle beteiligten Indexe (7, 3, 9), die im
Gesamtprogramm auftauchen, gegen (0, 1, 2) getauscht werden.

Ein vereinfachtes Beispiel, das keine sinnvolle Anwendung darstellt
aber das Problem auf das hier Fragliche reduziert, könnte so aussehen:


int liste[i]; //Wert von i soll durch den Pràprozessor
//ermittelt werden.
int summe;

int indexfunction(int j)
{
liste[j]++;
return;
}

main()
{
..
While (1) //Endlosschleife
{
...
indexfunction(7);
...
indexfunction(3);
...
indexfunction(9);
...
summe = liste[3] + liste[7] + liste[9];

}
}

In diesem Falle müsste der Pràprozessor also ein
"int liste[10]"
erzeugen - oder aber noch besser die Indexe optimieren bzw. neu
durchnumerieren zu:


int liste[3];
int summe;

int indexfunction(int j)
{
liste[j]++;
return;
}

main()
{
..
While (1) //Endlosschleife
{
...
indexfunction(0);
...
indexfunction(1);
...
indexfunction(2);
...
summe = liste[0] + liste[1] + liste[2];

}
}

Falls diese Optimierung nicht möglich ist, müsste man sie leider bei
jeder Programmànderung von Hand vornehmen.

Sind meine Überlegungen richtig? Wàre dieses Problem mit dem
Pràprozessor zu erschlagen? Gibt es auch andere und bessere
Möglichkeiten?

Für alle diejenigen, die sich jetzt noch fragen, wo dies sinnvoll
eingesetzt werden kann, noch Folgendes:

Die "indexfunction" bestimmt, ob ein Controllereingang von "0" nach
"1" gewechselt hat. Der aktuelle Zustand dea Controllereinganges wird
dabei ebenfalls an indexfunction übergeben. Die Variable "liste[i]"
hàlt dieses Ergeignis dadurch fest, dass sie zu "1" gesetzt wird.
Dabei ist "liste[i]" in Wirklichkeit ein Element aus einem struct
innerhalb eines struct-arrays. Für jeden Controllereingang, für den
dies notwendig ist, wird die Funktion mit einem anderen Index
aufgerufen. In der Folge werden die anderen Elemente des indizierten
Structs bei jedem Interruptaufruf solange veràndert, bis diese einen
gewünschten Zustand annehmen. Als Quittung hierfür wird dann liste[i)
wieder zu "0" gesetzt und der Controller ist damit bereit, den
nàchsten Übergang des Controllereinganges von "0" auf "1" zu
bearbeiten.

Die Indexierung der Stucts macht im Interrupt eine ressourcenschonende
Wiederholung (für jeden Controllereingang) durch "Do while" möglich,
die vom (Signal]controller unter "Mißbrauch" seiner
Signalbearbeitungsfeatures ebenso wie eine in der Schleife befindliche
Aufwàrtszàhlung der Indexierung in Hardware gegossen unterstützt wird.
Letzteres ist auch ein wichtiger Grund dafür, dass ich möglichst mit
einem Array und nicht mit einer verketteten Liste arbeiten möchte. Bei
letzterer sehe ich keinen Weg, die Verabeitung im Interrupt
"mißbràuchlich" über den superschnellen und ressourcensparenden
Signalpfad des Controllers zu leiten.

Hier wird auch klar, dass der aktuelle Zustand des Controllereinganges
im gleichen indizierten Struct mit abgespeichert werden muss und zwar
global. Denn ansonsten hat die indexfunktion beim nàchsten Aufruf
unter diesem Index keine Vergleichsmöglichkeit mehr, um einen
inzwischen stattgefundenen Wechsel des Eingangs zu detektieren. Es ist
unmöglich, hierfür eine nicht indizierte Variable zu benutzen, denn
dann würde der alte Wert eines Controllereinganges durch den alten
Wert eines anderen überschrieben.
 

Lesen sie die antworten

#1 Claus Reibenstein
21/10/2007 - 20:17 | Warnen spam
Paul Rosen schrieb:

ich bin in C, insbesondere bei dessen Pràprozessor noch etwas wackelig
auf den Beinen und es stellt sich folgendes Problem:

[...]

Daher die Frage: Gibt es eine Möglichkeit, schon im Pràprozessor, die
verwendeten Indexe abzutasten und daraus den zu definierenden Index
des eindimensionalen Feldes zu bestimmmen. Möglicherweise kann der
Pràprozessor auch noch durch Löschen entstandene Lücken eliminieren,
indem er die Aufrufe neu durchnumeriert. Zum Beispiel wird eine
verwendete Indexliste {7, 3, 9} zu {0, 1, 2} optimiert. Wichtig ist
dabei natürlich, dass alle beteiligten Indexe (7, 3, 9), die im
Gesamtprogramm auftauchen, gegen (0, 1, 2) getauscht werden.

Ein vereinfachtes Beispiel, das keine sinnvolle Anwendung darstellt
aber das Problem auf das hier Fragliche reduziert, könnte so aussehen:


int liste[i]; //Wert von i soll durch den Pràprozessor
//ermittelt werden.
int summe;

int indexfunction(int j)
{
liste[j]++;
return;
}

main()
{
...
While (1) //Endlosschleife
{

indexfunction(7);

indexfunction(3);

indexfunction(9);

summe = liste[3] + liste[7] + liste[9];
.
}
}



Das sinnvolle Einrücken von Schleifen musst Du noch üben :-)

Ich glaube nicht, dass der Pràprozessor der richtige Ansatz für Dein
Problem ist. Ich würde es eher mit einem enum versuchen, etwa so (nur
die relevanten Zeilen):

enum {Index7, Index3, Index9, IndexAnzahl};

int liste[IndexAnzahl];

indexfunction[Index7];
indexfunction[Index3];
indexfunction[Index9];

summe = liste[Index3] + liste[Index7] + liste[Index9];

Natürlich kannst (und solltest) Du für Index3 etc. sprechendere Namen
benutzen.

Gruß. Claus

Ähnliche fragen