Hallo zusammen. Von Assembler nach C umgestiegen, frage ich mich nun, wie man in C ein Makro schreibt. So schwer kann das eigentlich nicht sein, aber offensichtlich habe ich im Moment ein Brett vorm Kopf >_< In Assembler würde man ja schreiben: Name_des_Makros MAKRO befehle befehle #endm Wie würde man denn jetzt so etwas simples in C bewerkstelligen?
1 | |
C-Buch lesen...
Gast
#1189307
z.B. so
#define warte \
{ \
while(i++); \
}
Wobei Assembler Makros in C oft besser durch eine Funktion realisiert werden.
Gast
#1189317
> Kevin J. (Firma: FZ-Juelich) (noway)
Schwer zu glauben, dass es im FZ-Juelich kein C-Buch gibt...
Ah natürlich ja...Bücher vorn Kopf klatsch Hätte ich eines hier hätte ich auch nachgeschlagen -.- Solche Kommentare kann man sich doch schenken. Aber das hat ja auch was, indem man "Neulingen" einfach direkt einen vor den Bug ballert und ihnen die Motivation mit solch schlauen Sprüchen raubt... Zum Thema: Die Idee von Martin werde ich ausprobieren. Danke dafür.
Martins Lösung ist meiner Meinung nach nicht ganz vollständig (siehe
Parameterliste des Makros). ;-)
Definition des Makros:
#define warte(i)\
{ \
while(i++); \
}
Anwendung des Makros:
warte(1000);
Tschau Sven!
...und es ist meist sinnvoll, Makronamen in GROSSBUCHSTABEN zu schreiben, um sie von Funktionen/Variablen unterscheiden zu können.
> Die Idee von Martin werde ich ausprobieren. Danke dafür.
Es macht mehr Sinn sich an den Vorschlag von Karl heinz Buchegger zu
halten.
Sinn und Zweck eines Makros ist es doch, das der gleiche Code an
verschiedenen Stellen ausgeführt wird. Das erreichst Du am elegantesten,
durch eine Funktion.
Also z.B.1 | |
2 | |
3 | |
4 | |
5 | |
DEFINES werden eher dafür benutzt um Compilerabhängige Codeanpassungen vorzunehmen. Such einfach mal nach C Tutorial und lies doch ein paar Seiten.
Dieter Engelhardt wrote: > Sinn und Zweck eines Makros ist es doch, das der gleiche Code an > verschiedenen Stellen ausgeführt wird. Das erreichst Du am elegantesten, > durch eine Funktion. Die hat aber, im Gegensatz zu einem "echten" Makro (das nur eine Textersetzung vornimmt) einen oft nicht erwünschten Overhead. In dem Fall sollte man die fragliche Funktion eventuell inline deklarieren...
Gast
#1189517
Johannes M. wrote:
> Fall sollte man die fragliche Funktion eventuell inline deklarieren...
Und nen aktuellen GCC dazu benutzen...
Sven P. wrote:
> Und nen aktuellen GCC dazu benutzen...
Na, das doch sowieso...
@ Dieter Engelhardt: Hallo Dieter! Es tut mir leid, aber da kann ich Dir so nicht zustimmen. 1) Mit Funktionen erreichst Du, daß ein und der selbe Code von unterschiedlichen Stellen des Programms aus zur Laufzeit angesprungen und ausgeführt werden kann. 2) Definierst Du ein Makro und benutzt es an mehren Stellen, wird immer wieder der selbe Code beim Übersetzen des Quellcodes in das Programm eingefügt (an jeder Stelle, an der das Makro benutzt wurde). Aus diesem Grund sollte man auch mit Makros vorsichtig sein, um das Programm nicht aufzublähen. Aufgrund der fehlenden Sprünge läuft es aber schneller. Die Verwendung von Makros lohnt sich bei kurzen Befehlssequenzen. @Karl heinz Buchegger: >Wobei Assembler Makros in C oft besser durch eine Funktion realisiert >werden. Was meinst Du damit genau? In Martins Beispiel handelt es sich doch um ein C-Makro. Tschau Sven!
@Johannes M. Mit inline definierte Funktionen als Alternative hast du natürlich recht. Gibt es zwischen inline definierten Funktionen und Makros irgendwelche wichtigen Unterschiede bei der Abarbeitung?
Gast
#1189534
Ihr habt alle die Frage nicht verstanden.
So und NUR so schreibt man ein einfaches Makro in C:
printf("ein einfaches Makro in C:");
Gast
#1189542
makros mit #define wait(i) {while(...);} funktionieren bei
if (test(foo)) wait(i); else bar();
Da merkst du selbst, daß das nicht funktioniert.
Deshalb verwendet man
#define wait(i) do {...} while(0)
weil da das Semikolon obligatorisch ist, und es dann kein null-statement
ist, was dir jede if/while/... Abfrage verhunzt.
Sven Woehlbier wrote: > #define warte(i)\ > { \ > while(i++); \ > } > > Anwendung des Makros: > warte(1000); Tolles Makro :-o Frage: Wie lange zählt das denn hoch? Antwort: bis zum Überlauf der übergebenen Zahl. Überhaupt bin ich mir nicht ganz sicher, dass genau dieser Aufruf funktionieren wird. Denn was macht der Preprozessor daraus? > { while(1000++); } Macht das Sinn?
Sven Woehlbier wrote: >>Wobei Assembler Makros in C oft besser durch eine Funktion realisiert >>werden. > > Was meinst Du damit genau? In Martins Beispiel handelt es sich doch um > ein C-Makro. Es gibt genügend Fallstricke bei C-Makros. Legionen von Programmieren sind darauf hereingefallen und werden es auch weiter tun. Solange man weiß was man tut, können Makros nützlich sein. Hab selbst schon jede Menge Unfug mit Makros angestellt. Aber irgendwann kommt man zur Erkenntnis, das man abwägen soll und muss, ob man eine bestimmte Funktionalität mit Makros oder mit einer Funktion realsiert. Makros als Funktionsersatz für generische Funktionen sollte gesetzlich verboten werden.
1 | |
und dann viel Spass beim Suchen warum zwar
1 | |
funktioniert, sich aber
1 | |
"seltsam" verhält (nur um mal eines der prominentesten Beispiele zu benutzen. Die Liste ist beliebig verlängerbar). Oder warum in
1 | |
die Funktion NrOfEntries manchmal, aber nicht immer, 2 mal aufgerufen wird. Wobei das bei einer Abzählfunktion ja noch relativ glimpflich ist, wenn aber von einem Konto ein bestimmter Betrag manchmal 2 mal abgebucht wird, dann erklär das mal deinem Kunden. Und vor allen Dingen find diesen Bug mal in einem Programm. Die Fehlermeldung deines Kunden lautet: Manchmal wird eine Abbuchung doppelt gemacht. Und dann stell da mal die Beziehung dazu her, dass du den Abbuchbetrag gegen einen Maximalbetrag getestet hast und das das die Ursache für die 2-te Abbuchung war.
Lothar Miller wrote: > Überhaupt bin ich mir nicht ganz sicher, dass genau dieser Aufruf > funktionieren wird. Denn was macht der Preprozessor daraus? >> { while(1000++); } > Macht das Sinn? Ich bin auch neugierig welche und wie verständlich die Fehlermeldungen des Compilers sind, sollte jemand mal auf die Idee kommen
1 | |
zu schreiben :-)
Gast
#1189562
> Hätte ich eines hier hätte ich auch nachgeschlagen -.- Alternative -> Internet-Tutorials! Du lernst heute soviel Neues... ;-) > Solche Kommentare kann man sich doch schenken. Aber das hat ja auch > was, indem man "Neulingen" einfach direkt einen vor den Bug ballert und > ihnen die Motivation mit solch schlauen Sprüchen raubt... Was glaubst du eigentlich wie demotivierend Fragen wie die deine oben sind? Irgendwann hat gar keiner mehr Lust zu antworten...
Kevin J. wrote: > Ah natürlich ja...Bücher *vorn Kopf klatsch* > Hätte ich eines hier hätte ich auch nachgeschlagen -.- Solche Kommentare > kann man sich doch schenken. Aber das hat ja auch was, indem man > "Neulingen" einfach direkt einen vor den Bug ballert und ihnen die > Motivation mit solch schlauen Sprüchen raubt... Wenn ich dir so zuhöre wundert es mich direkt wie Millionen von Programmierern vor der "Erfindung" des Internet überhaupt Programmieren erlernen konnten. Man war das damals demotivierend die IBM JCL Manuals tage-, ja wochenlang zu studieren.
@ Lothar Miller:
Kritik angekommen! Habe leider das Beispiel von Martin zu kritiklos
übernommen. Hier jetzt aber ein lauffähiges Makro.
#define DELAY(pause){\
clock_t start = clock();\
while( (((clock()-start)*1000)/CLK_TCK) < pause );\
}
Sven Woehlbier wrote: > @ Lothar Miller: > > Kritik angekommen! Habe leider das Beispiel von Martin zu kritiklos > übernommen. Hier jetzt aber ein lauffähiges Makro. > > > #define DELAY(pause){\ > clock_t start = clock();\ > while( (((clock()-start)*1000)/CLK_TCK) < pause );\ > } Das kann (muss nicht) wiederrum für denjenigen, der dieses Makro benutzt zu seltsamen Effekten führen. Überleg dir einfach bei jedem(!) Makro das du schreibst, was wohl passieren wird, wenn du als Argument eine Variable++ einsetzt bzw. das Ergebnis eines Funktionsaufrufs benutzt.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
verhält sich völlig anders, als man intuitiv beim Studim dieser Codezeilen erwarten würde. Um Ordnung in dieses Chaos zu bekommen, muss man die Internals von DELAY kennen, etwas was ich bei einer gleichnamigen Funktion delay() nicht muss. Immerhin warst du freundlich genug und hast den Makro Namen gross geschrieben, so dass jemand, der dieses Makro verwendet gewarnt ist und das Makro studiert ehe er es benutzt. Aber Hand aufs Herz: Willst du jedesmal, wenn du vorgefertigte Funktionalität benutzt erst überlegen müssen, wie das Makro wohl expandiert und ob es da mglw. zu Semantischen Fehlern kommen kann?
Gast
#1189608
#define DELAY(pause){\
clock_t start = clock();\
while( (((clock()-start)*1000)/CLK_TCK) < pause );\
}
das schreibt man so
#define DELAY(pause)do {\
clock_t start = clock();\
while( (((clock()-start)*1000)/CLK_TCK) < pause );\
} while(0)
oder für GCC auch so,
#define DELAY(pause)({\
clock_t start = clock();\
while( (((clock()-start)*1000)/CLK_TCK) < pause ); 1; \
})
da kann man es nähmlich auch als Expression nutzen, wie wenn es eine
Funktion wäre, z.B. foo?DELAY(100):bar oder auch anders, ist für
Delay vielleicht nicht so angebracht.
Gast
#1189624
#define DELAY(pause)do {\
clock_t start = clock();\
while( (((clock()-start)*1000)/CLK_TCK) < pause );\
} while(0)
Sollte so sein, habe mir den Code zu wenig angesehen.
#define DELAY(pause)do {\
clock_t end = clock() + ((pause)*1000/CLK_TCK);\
while( (((clock()) < end );\
} while(0)
@Karl heinz Buchegger Hallo Karl-Heinz! Vielen Dank, für Deine Hinweise! Ich mußte erst auf Lothar reagieren, und wenigstens ein korrektes Makro präsentieren. Auf die Idee das Makro mit Funktionsaufrufen und Variablen auszuprobieren, bin ich ehrlich gesagt noch nicht gekommen. Ich habe es ausschließlich mit einer Konstanten im Aufruf benutzt. z.B. DELAY(1000); Hintergrund bei der Sache ist, der Borland-Compiler, den ich hier benutze, unterstützt das alte delay() nicht mehr. Manchmal ist man eben nicht ganz frei in der Auswahl der Werkzeuge. Insgesamt hast Du aber recht, für einen anderen Programmierer könnte die Verwendung des Makros problematisch sein. Ich glaube, wenn es dann etwas makro-ähnliches sein muß, sind mir die Inline Funktionen dann doch lieber. Vielen Dank! Tschau Sven!
Sven Woehlbier wrote: > Ich glaube, wenn es dann etwas makro-ähnliches sein muß, sind mir die > Inline Funktionen dann doch lieber. Du bist am richtigen Weg! genauso effizient wie Makros, nur dass sich der Compiler um diese ganzen kleinen Fallen kümmert :-)
Gast
#1189635
@... (Gast)
>> Schwer zu glauben, dass es im FZ-Juelich kein C-Buch gibt...
immer wieder tauch so ein A... statt was helfen nur so was! klar
bestimmt hat er selber keine Ahnung von C oder überhaupt aber Wichtig
ist hier irgendwelche misst zu schreiben!
Gruß
Gast
#1189678
> genauso effizient wie Makros
Das stimmt so nicht, weder bei der Ausführung, noch in der
Programmierung.
Da Macros ja nur Textersetzungen sind, macht der Compiler keine
Typumwandlungen. Bei Funktionen aber schon. Auch wenn man sie nicht
braucht.
Wenn man Glück hat, haut's der Optimizer wieder raus. Es gibt da aber
noch andere Sachen, da gehts einfach nicht.
Und das oben angegebene max() Macro kann man z.B. für jeden möglichen
Datentyp, also ints, longs, shorts, quads, floats, doubles, singed oder
unsigned, pointer (macht keinen Sinn, geht aber), usw. benutzen. Sogar
Kombinationen sind möglich.
Davon mal abgesehen sind viele Dinge mit inlined functions schlichtweg
unmöglich. Sogar mit C++ Templates. Wer Macros links liegen lässt, weil
sie ihm zu gefährlich sind, der wird m.E. niemals effizient C/C++
programmieren lernen. Warum sind wohl die System headers alle voll mit
Macros?
Gast
#1189679
Hallo, eine Delay Funktion würde ich sowieso als Funktion machen, da weiß man wie lange diese braucht, da der Datentyp in der Funktion fest ist. Wenn du eine solche Funktion als MAKRO machst ist sie je nach Datentyp unterschiedlich langsam. Angeommen du hast einen 8-Bit Controller:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Urs wrote: > Da Macros ja nur Textersetzungen sind, macht der Compiler keine > Typumwandlungen. Bei Funktionen aber schon. Auch wenn man sie nicht > braucht. Das ist natürlich ein Argument. Stimme ich zu. > Und das oben angegebene max() Macro kann man z.B. für jeden möglichen > Datentyp, also ints, longs, shorts, quads, floats, doubles, singed oder > unsigned, pointer (macht keinen Sinn, geht aber), usw. benutzen. Sogar > Kombinationen sind möglich. Yep. Und allen gemeinsam sind die Fallen die man damit stellt :-) Man muss also immer abwägen was einem wichtiger ist: "code and forget" bei möglicherweise etwas verminderter Laufzeit (um die Aussage von oben 'genauso effizient' etwas zu entschärfen) oder "code and remember what pitfalls are waiting" aber dafür am schnellsten. > Davon mal abgesehen sind viele Dinge mit inlined functions schlichtweg > unmöglich. Yep. Alles was mit Token-pasting und concatination zu tun hat. > Sogar mit C++ Templates. Wer Macros links liegen lässt, weil > sie ihm zu gefährlich sind, der wird m.E. niemals effizient C/C++ > programmieren lernen. Warum sind wohl die System headers alle voll mit > Macros? Weil die Header uralt sind und sich noch niemand die Mühe gemacht hat sie auf inline umzuschreiben. Behaupte ich jetzt mal.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.