Funktionsname mit Makro ersetzen

(Firma: keine) #3492417
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ß!
(Firma: keine) #3492459
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.
Gast #3492467
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.
#3492470
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.
(Firma: keine) #3492477
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.
Gast #3492484
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.
Gast #3492488
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();
Gast #3492544
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.
(Firma: keine) #3492560
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.
Moderator #3492688
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.
Moderator Persönliche Seite #3492982
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).
Gast #3493002
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!
(Firma: keine) #3493009
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
(Firma: keine) #3493049
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.
(Firma: keine) #3493079
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" ;-) .
#3493150
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
}
Angehängte Dateien:
#3494048
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren