Forum: Compiler & IDEs Funktionsname mit Makro ersetzen


von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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ß!

von Max H. (hartl192)


Lesenswert?

marco polo schrieb:
> #define EXECFUNCTION(wert)  (function(wert)test)

Probier mal das 'test' durch einen ';' zu ersetzen.

von Peter II (Gast)


Lesenswert?

Was soll dieser Unsinn - das geht nicht!!!!!!!!

define ist ein Textersetzung, sie kann also NIEMALS mit werten einer 
scheife einen Funktionsnamen zusammenbauen.

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Tom K. (ez81)


Lesenswert?

Das funktioniert so nur in interpretierten Sprachen wie perl, php etc.

Der Preprocessor macht aus deinem Code dies (mit gcc -E testbar):
1
int main()
2
{
3
int i;
4
5
for(i=1;i<=10;i++)
6
{
7
   (function(i)test);
8
}
9
10
return 0;
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.

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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.

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

Gute Idee mit den Funktionszeigern,

Danke!

von Peter II (Gast)


Lesenswert?

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.

von uiipsdof (Gast)


Lesenswert?

>Ich möchte das der
>Preprozessor mir komfortabel die Funktionen erzeugt:

So, z.B.:

#define FUNCTION(suffix)  FUNCTION##suffix##_test()

extern FUNCTION(_66);


gibt (gcc -E):

# 1 "<built-in>"
# 1 "<command-line>"

extern FUNCTION_66_test();

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

uiipsdof schrieb:
> So, z.B.:

Jaja, dann mach das mal mit 'ner Variablen statt Deiner "_66".

von Floh (Gast)


Lesenswert?

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.

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

So geht's:
1
#include <boost/preprocessor.hpp>
2
3
#define EXECFUNCTION(z, I, _) function##I##test();
4
5
int main(void) {
6
7
  BOOST_PP_REPEAT_FROM_TO(1, 11, EXECFUNCTION, _)
8
9
  return 0;
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.

von Oliver S. (oliverso)


Lesenswert?

Na ja, ob das der TO aber so genau wissen wollte ;)

Oliver

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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? :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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).

von Amateur (Gast)


Lesenswert?

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!

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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();
6
7
void function1test()
8
{
9
  printf("function1 \n");
10
}
11
12
void function2test()
13
{
14
  printf("function2 \n");
15
}
16
17
void function3test()
18
{
19
  printf("function3 \n");
20
}
21
int main(void) {
22
  BOOST_PP_REPEAT_FROM_TO(1, 4, EXECFUNCTION, _);
23
  return EXIT_SUCCESS;
24
}

output:

function1
function2
function3

von Oliver (Gast)


Lesenswert?

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

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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

von Ste N. (steno)


Lesenswert?

1
int main(void) {
2
  BOOST_PP_REPEAT_FROM_TO(1, 4, EXECFUNCTION, _);
3
  return EXIT_SUCCESS;
4
}

Und wo ist jetzt deine Variable i und die For Next Schleife?

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

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.

von Marco P. (Firma: keine) (marcopolo)


Lesenswert?

Steffen N. schrieb:
>
1
> int main(void) {
2
>   BOOST_PP_REPEAT_FROM_TO(1, 4, EXECFUNCTION, _);
3
>   return EXIT_SUCCESS;
4
> }
5
>
>
> 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" ;-) .

von Tom K. (ez81)


Angehängte Dateien:

Lesenswert?

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.
1
#include "a.h"
2
int main(void)
3
{
4
    FROM_0_TO_7(test_, "foo");
5
}
wird zu
1
int main(void)
2
{
3
    do{ test_0("foo"); test_1("foo"); test_2("foo"); test_3("foo"); test_4("foo"); test_5("foo"); test_6("foo"); test_7("foo"); } while 0;
4
}

von Oliver (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.