Hallo,
ich möchte ein C-Makro benutzen um eine Zahl in einen Funktionsnamen
einzufügen. Es existieren folgende Funktionen im code welche ich
nacheinander ausführen möchte:
void function1test();
...
void function10test();
Ich hab mir das folgendermassen gedacht:
#define EXECFUNCTION(wert) (function(wert)test)
int main()
{
int i;
for(i=1;i<=10;i++)
{
EXECFUNCTION(i);
}
return 0;
}
Leider funktioniert das nicht, der Compiler meckert ein ; an, da er
folgendes erwartet:
function(argument);
Ich möchte aber nur die Zahl mit dem wert ersetzen. Geht das überhaupt?
Danke und Gruß!
Was soll dieser Unsinn - das geht nicht!!!!!!!!
define ist ein Textersetzung, sie kann also NIEMALS mit werten einer
scheife einen Funktionsnamen zusammenbauen.
Peter II schrieb:> Was soll dieser Unsinn - das geht nicht!!!!!!!!>> define ist ein Textersetzung, sie kann also NIEMALS mit werten einer> scheife einen Funktionsnamen zusammenbauen.
Naja Unsinn würd ich es nicht nennen, aber du hast Recht der
Preprozessor macht nur eine Textersetzung. Ich möchte das der
Preprozessor mir komfortabel die Funktionen erzeugt:
void function1test();
...
void function10test();
Und das mit einem Makro.
marco polo schrieb:> Ich möchte das der> Preprozessor mir komfortabel die Funktionen erzeugt:
Das geht nicht. Mach ein Array mit Funktionspointern, iteriere dadurch
und rufe die Pointer auf.
marco polo schrieb:> Peter II schrieb:>> Was soll dieser Unsinn - das geht nicht!!!!!!!!> Ich möchte das der> Preprozessor mir komfortabel die Funktionen erzeugt:
kann schon sein das du das willst, sinn macht es noch lange nicht.
Man müsste das mit einem Array aus funktionspointer lösen, aber wenn du
bis jetzt nicht verstanden hast warum es so nicht geht, ist da noch
etwas hoch für dich.
Das funktioniert so nur in interpretierten Sprachen wie perl, php etc.
Der Preprocessor macht aus deinem Code dies (mit gcc -E testbar):
1
intmain()
2
{
3
inti;
4
5
for(i=1;i<=10;i++)
6
{
7
(function(i)test);
8
}
9
10
return0;
11
}
Je nachdem, was Du vorhast, sind Alternativen vielleicht ein Array mit
Funktionszeigern, ein Unittesting-Framework für C oder automatische
Code-Erzeugung mit einer dafür geeigneten Sprache¹ als Teil des
Build-Prozesses.
Peter II schrieb:> marco polo schrieb:>> Peter II schrieb:>>> Was soll dieser Unsinn - das geht nicht!!!!!!!!>> Ich möchte das der>> Preprozessor mir komfortabel die Funktionen erzeugt:>> kann schon sein das du das willst, sinn macht es noch lange nicht.>> Man müsste das mit einem Array aus funktionspointer lösen, aber wenn du> bis jetzt nicht verstanden hast warum es so nicht geht, ist da noch> etwas hoch für dich.
Auf solche Antworten kann ich verzichten. Bitte Peter vergnüg dich doch
wo anders.
marco polo schrieb:> Peter II schrieb:>> marco polo schrieb:>>> Peter II schrieb:>>>> Was soll dieser Unsinn - das geht nicht!!!!!!!!>>> Ich möchte das der>>> Preprozessor mir komfortabel die Funktionen erzeugt:>>>> kann schon sein das du das willst, sinn macht es noch lange nicht.>>>> Man müsste das mit einem Array aus funktionspointer lösen, aber wenn du>> bis jetzt nicht verstanden hast warum es so nicht geht, ist da noch>> etwas hoch für dich.>> Auf solche Antworten kann ich verzichten. Bitte Peter vergnüg dich doch> wo anders.
Der Versuch zeigt aber das du überhaupt nicht verstanden hast wie eine
define arbeitet. Und das sind die Grundlagen von C. Funktionspointer
kommen bei den Grundlagen nicht vor.
Keep it simple:
marco polo schrieb:> int main()> {> int i;>
function1test();
function2test();
function3test();
function4test();
function5test();
function6test();
function7test();
function8test();
function9test();
function10test();
> return 0;> }
Problem gelöst und keine Verständnisprobleme.
Ursprünglich hatte ich dieses Makro verwendet:
#define EXECFUNCTION(name, wert) (function##name##test(wert))
und das dann z.B. so aufgerufen
int i=2;
EXECFUNCTION(1, i);
Funktioniert, aber nur mit einer Funktion! Ich dachte halt der
Preprozessor kann ein bischen mehr und wie ein script oder awk auch
Schleifen mit Iterationen ausführen. Warscheinlich war ich auf dem
Holzweg.
#define EXECFUNCTION(z, I, _) function##I##test();
4
5
intmain(void){
6
7
BOOST_PP_REPEAT_FROM_TO(1,11,EXECFUNCTION,_)
8
9
return0;
10
}
Man braucht dazu die Boost.Preprocessor-Bibliothek, die man hier
bekommt:
http://www.boost.org/
Boost ist zwar eine C++-Bibliothek, das Präprozessorzeugs funktioniert
aber auch mit C.
Vielen Dank Yalu, ich werds gleich mal ausprobieren!
Oliver S. schrieb:> Na ja, ob das der TO aber so genau wissen wollte ;)>> Oliver
Noch so einer mit ner unqualifizierten Bemerkung. Was ist denn das hier
für ein negatives Karma? :-)
marco polo schrieb:> Gute Idee mit den Funktionszeigern,
Das widerspricht übrigens deinem dem unmittelbar voran gehenden Posting
("auf solche Antworten kann ich verzichten").
Ja, man kann (wie das von Yalu gepostete Beispiel zeigt) natürlich
den Präprozessor für ziemlich viel Quatsch missbrauchen, für den er
nie konzipiert worden ist.
Aber man muss das nicht tun, und sehr oft finden sich viel elegantere
Lösungen. Ein Array mit Funktionszeigern wurde dir ja schon genannt,
aber auch eine Liste kann hier Sinn haben (wenn "next_function"-Zeiger
nicht NULL, dann mach dort weiter).
Wehe hier sagt noch einer: "Das geht nicht oder ist Unsinn", dann kommt
marc-o polo aus dem Bildschirm und gibt Dir was auf die Tastatur!
Was ich nur nicht verstehe ist was soll das Ganze?
Selbst wenn ich automatisiert 99 Unikate von Funktionsnamen generiere,
gibt es die Funktionen selbst doch nicht.
Automatisiert kann ich mit vielen Tricks auch 99 Funktionen erstellen,
aber über den A-H-Effekt geht das ganze wohl nicht hinaus.
Oder kennt hier jemand einen, der 99 gleiche Funktionen gebrauchen kann?
Kann es sein, dass hier Quatsch mit Sauce produziert werden soll?
Oder ist's für 'ne Doktorarbeit? Ihr wisst schon: Viel Text mit
reduzierter Aussagekraft - geht aber!
Jörg Wunsch schrieb:> marco polo schrieb:>> Gute Idee mit den Funktionszeigern,>> Das widerspricht übrigens deinem dem unmittelbar voran gehenden Posting> ("auf solche Antworten kann ich verzichten").>> Ja, man kann (wie das von Yalu gepostete Beispiel zeigt) natürlich> den Präprozessor für ziemlich viel Quatsch missbrauchen, für den er> nie konzipiert worden ist.>> Aber man muss das nicht tun, und sehr oft finden sich viel elegantere> Lösungen. Ein Array mit Funktionszeigern wurde dir ja schon genannt,> aber auch eine Liste kann hier Sinn haben (wenn "next_function"-Zeiger> nicht NULL, dann mach dort weiter).
Ja da war ich wohl etwas schnell mit dem Zurückschreiben. Wenn mir
jemand was über Sinn und Unsinn erzählen will, werd ich immer hellhörig.
Geht mir im Übrigen auch bei Produkten so, die Smart im Namen haben.
Yalus Lösung funktioniert super (wie unten); Funktionszeiger erfüllen
sicher den Zweck auch. Aber das probier ich morgen.
Vielen Dank Euch für die Mühe!
1
#include<stdio.h>
2
#include<stdlib.h>
3
#include<boost/preprocessor.hpp>
4
5
#define EXECFUNCTION(z, I, _) function##I##test();
marco polo schrieb:> Yalus Lösung funktioniert super (wie unten); Funktionszeiger erfüllen> sicher den Zweck auch. Aber das probier ich morgen.
Ich hol' schonmal Popcorn ;)
Oliver
Oliver schrieb:> marco polo schrieb:>> Yalus Lösung funktioniert super (wie unten); Funktionszeiger erfüllen>> sicher den Zweck auch. Aber das probier ich morgen.>> Ich hol' schonmal Popcorn ;)>> Oliver
Mach das, aber pass auf das dir nicht die Tränen kommen :-P
Amateur schrieb:> Wehe hier sagt noch einer: "Das geht nicht oder ist Unsinn", dann kommt> marc-o polo aus dem Bildschirm und gibt Dir was auf die Tastatur!>> Was ich nur nicht verstehe ist was soll das Ganze?>> Selbst wenn ich automatisiert 99 Unikate von Funktionsnamen generiere,> gibt es die Funktionen selbst doch nicht.>> Automatisiert kann ich mit vielen Tricks auch 99 Funktionen erstellen,> aber über den A-H-Effekt geht das ganze wohl nicht hinaus.> Oder kennt hier jemand einen, der 99 gleiche Funktionen gebrauchen kann?>> Kann es sein, dass hier Quatsch mit Sauce produziert werden soll?>> Oder ist's für 'ne Doktorarbeit? Ihr wisst schon: Viel Text mit> reduzierter Aussagekraft - geht aber!
Okay, ich gebs zu. Ich habe mehr als 99 Unikatfunktionen, und ja ich
kann das gut gebrauchen.
Man kann z.B. Portpin Eigenschaften setzen für Unit-Tests. Oder
Laufzeiten automatisch generierter Funktionen ermitteln.
Sicher kann man alles viel einfacher machen, aber ich bin halt nicht so
helle wie Eure Majestät.
>> Und wo ist jetzt deine Variable i und die For Next Schleife?
Hallo Steffen,
mit einer zur Laufzeit ausgeführten Schleife funktioniert es nicht, da
der Preprocessor vor dem Compile über den C/C++-code Text läuft und nur
Textersetzungen macht. i war nur ein Vorwand um mein Vorhaben zu
verbildlichen. Das Makro BOOST_PP_REPEAT_FROM_TO ist eine Erweiterung,
mit der man automatisch C/C++-Code Text o.ä erzeugen kann.
Der gcc Preprocessor kann keine Zahl incrementieren und diese in den
C/C++-Code als Text einfügen, deswegen die boost-lib.
Soviel zu meinem "Text mit reduzierter Aussagekraft" ;-) .
Noch eine abwegige Idee, die ohne boost auskommt:
Alle möglichen Schleifen in einem Header vordefinieren. Diesen schreibt
man sinnvollerweise nicht von Hand. Irgendwann wird es wahrscheinlich
sehr langsam oder der Preprocessor kommt an seine Grenzen.
Tom K. schrieb:> Noch eine abwegige Idee,
Ich hab auch eine, die ist noch abwegiger:
C/C++-Buch kaufen, und die Sprachen lernen. Ist aber ziemlich
oldschool...
Oliver
marco polo schrieb:> Man kann z.B. Portpin Eigenschaften setzen für Unit-Tests.
Du willst also die Arduino-Lib nachentwickeln, bloß mit erheblich mehr
Aufwand.
Da sind nämlich Funktionen drin für den Pinzugriff als Nummer.
Die Lib ist aber auch kein Hexenwerk. Man braucht nur ein Array mit den
Portadressen (A..L) und eins mit 8 Bitmasken.
Schon ab 2 Funktionen, die sich ähnlich sind, überlege ich, was ist der
Unterschied und versuche sie zusammen zu fassen.