2016-04-08 21 views
0

Ich frage mich, ob es möglich ist, etwas wie eine Reihe von Makros zu erstellen. Ich habe den folgenden Code implementiert, die funktioniert:Array von Makros in c - ist es möglich

struct led_cmds_ 
{ 
    ioport_pin_t *commands[LED_COUNT] ; 
} ; 
struct led_cmds_ the_led_cmd_ ; 

void populate() { 
    the_led_cmd_.commands[0] = SPECIFICPIN(0); 
} 

und in Haupt:

int main(void) 
{ 
//..... 
populate(); 
LED_On(the_led_cmd_.commands[0]); 
} 

SPECIFICPIN (x) Makro definiert als:

#define SPECIFICPIN(X) (LED##X##_PIN) 

Was denn ich hatte gehofft, ist ein Weg zu einem Weg, so etwas zu tun:

#define ioport_pin_t* ARR_LED[LED_COUNT] \ 
for (int j = 0; j < LED_COUNT; j++) ARR_LED[j] = SPECIFICPIN(j); 

und dann nur noch die folgenden rufen, wenn ich

LED_On(ARR_LED[some_number]) 

den spezifischen Stift verwenden möchten, wenn ich versuchen zu tun, dass ich ein ARR_LED bekommen nicht deklarierte Fehler (erste in dieser Funktion).

Wenn ich versuche, SPECIFICPIN zu nennen (x), wobei x einen int Iterator in einem zum Beispiel für Schleife ist, erhalte ich eine Fehlermeldung, dass so etwas wie ‚LEDx_PIN‘ nicht angemeldete ...

+0

Sie wissen nicht, ob Sie den gcc-Toolchain verwenden, aber Sie müssen C99 verwenden für avr-gcc (und es ist die Unterstützung Bibliotheken) sowieso - in der Regel mit -Os kombiniert. Warum nicht bei Inline-Funktionen bleiben? –

+0

Der Compiler weiß nichts über Makros, weil sie vor dem Aufruf des Compilers durch den * Präprozessor * ersetzt werden. Daher ist ein Array von Makros unmöglich –

+0

Warum sollten Sie bei der Arbeit mit Hardwareregistern ein Array von Zeigern wünschen?Das ist fischartiger Code. – Lundin

Antwort

4

Sie müssen sich auf Ihre Arbeit Terminologie. Ein Array von Makros ist nicht möglich. Makros sind kein Datentyp, sondern reine Textersetzung, bevor Ihr Programm tatsächlich kompiliert wird.

Ich denke, "füllen Sie ein Array mit Makros" ist, was Sie tun möchten. Aber es ist nicht möglich, das in einer Kompilierzeitschleife zu tun - Was Sie mit Ihrem ioport_pin_t Makroversuch zu erreichen scheinen. Makros sind nicht in der Lage, mehr Instanzen von Textelementen zu erweitern, als Sie ursprünglich angegeben haben. Es gibt keine solche Funktion wie eine Schleife zur Kompilierzeit durch Makroerweiterungen und eine wiederholte Expansion von Makros.

Ihre for Schleife zur Laufzeit, während das Makro zur Kompilierungszeit erweitert wird. Sobald Sie sich bewusst gemacht haben, was der Präprozessor macht, was der Compiler macht und was zur Laufzeit vom fertigen Programm gemacht wird, werden Sie sehen, dass das nicht funktioniert.

So etwas wie

#define P(X) {(LED##X##_PIN)} 

ioport_pin_t *commands[LED_COUNT] = { 
    P(0), P(1), P(2),......} 

#undefine P 

Wäre die nächste Sache möglich sein, was Sie scheinen zu wollen. Beachten Sie, dass die Hauptverwendung des Vorprozessors nicht darin besteht, den Tippaufwand zu sparen - Sie würden besser mit der Kopie & einfügen in Ihrem Editor arbeiten, die gleiche Sache erreichen und einen klareren Code haben.

+0

Kopieren und Einfügen verletzt die DRY-Regel, und es ist [sehr leicht, Fehler zu machen] (https://software.intel.com/en-us/blogs/2015/04/22/the-last-line-effect) –

+0

Wenn copy & paste * klarstellt, was Ihr Programm macht (wiederholtes Initialisieren von Array-Mitgliedern), verletzt es keine Regel IMHO. Zumindest können Sie sofort sehen, was passiert, Sie verschmutzen nicht den Namensraum des Vorprozessors mit (vorzugsweise) kurzen #Definitionen. Und: Es ist * generell * sehr einfach Fehler in C zu machen ..... – tofro

+0

Danke für die Hilfe. Ich habe eine Reihe von Präprozessordirektiven wie folgt gemacht: #if LED_COUNT == n füge zum Array an Position n -1 hinzu, definiere LED_COUNT, definiere es erneut als n-1 und rufe dann #elif LED_COUNT == n-1 auf und mache das bis auf 0 –

0

Ein Array als Tofro Antwort ist der Weg zu gehen. Jedoch in Fällen, die nicht einfach mit einer Reihe gelöst werden könnten, dann ist es eine andere Art und Weise mit dem Schalter

#define SPECIFICPIN(X) (LED##X##_PIN) 

void setpin(int pin, int value) 
{ 
    switch (pin) 
    { 
    case 1: 
     SPECIFICPIN(1) = value; 
     doSomething(); // if needed 
     break; 
    case x: ... 
    default: ... 
    } 
} 
Verwandte Themen