Rheinwerk Computing :: C von A bis Z - 10.2 Makros und Konstanten – »#define« (2023)

10.2Makros und Konstanten - "#define" Rheinwerk Computing :: C von A bis Z - 10.2 Makros und Konstanten – »#define« (3)

Schwindler#definierenEs ist möglich, Strings anzugeben, die vor dem Kompilieren des Programms durch einen anderen String ersetzt werden. Sie erinnern sich wahrscheinlich noch aus dem vorigen Kapitel, wie ein Programm kompiliert wird. Auch hier ist es durch das Schild gekennzeichnet#Es lässt den Präprozessor seine Arbeit erledigen, bevor der Compiler das junge Programm in Assembler und dann in Maschinensprache übersetzt. Die Syntax vondefinierenDirektive sieht so aus:

#Identifikator-Identifikator-Ersatz definieren#Identifikator-Identifikator-Ersatz definieren(identifier_list)

In der ersten Syntaxbeschreibung wird eine symbolische Konstante definiert und im zweiten Fall ein Makro.

10.2.1Symbolische Konstanten mit "#define"

Hier sehen Sie ein erstes Beispiel eines Programms, das eine symbolische Konstante definiert:

/* define1.c */#incluye <stdio.h>#incluye <stdlib.h>#define EINS 1int main(void) { printf("%d\n",EINS); desenvolvido EXIT_SUCCESS;}

Kein Programm, jede symbolische KonstanteGLEICHauf den Wert 1 gesetzt. Beim Kompilieren des Programms werden alle Namen vor dem Kompilieren eingeschlossenGLEICHdurch den Präprozessor im Quellcode durch den Wert 1 ersetzt. die KonstanteGLEICHmuss nicht wie im Beispiel in Großbuchstaben geschrieben werden. Dies dient nur der besseren Übersicht. Aber Achtung, folgendes funktioniert nicht:

printf("GLEICH");

In diesem Fall ist es tatsächlich der String"GLEICH"auf dem Bildschirm angezeigt wird und nicht der Wert 1. Das bedeutet, dass die KonstanteGLEICHnicht ersetzt durch 1.


Marke

Denk daran, dass#definieren-Makros sind konstant. Einmal definierte Konstanten können zur Programmlaufzeit nicht mehr geändert werden.

Was ist der Vorteil solcher Definitionen? Folgendes Programm soll dies demonstrieren:

/* kreisber.c */#include <stdio.h>#include <stdlib.h>/* Unter Linux muss das Compiler-Flag -lm * auch für math.h angegeben werden: * gcc -o synkonst2 symkonst2.c - lm */#include <math.h>#define PI 3.1415926f/* Programm zur Berechnung der Kreisfläche (A), des Durchmessers (d)* und des Umfangs (U) und des Durchmessers aus dem Umfang* / Bereich des leeren Kreises (leer) { Float A, d; printf("Geben Sie den Durchmesser des Kreises ein: "); scan("%f", &d); A = d*d*PI / 4; printf("Fläche des Kreises ist %f\n", A);} void diameter(void) {float A, d; printf("Geben Sie die Fläche des Kreises ein: "); scan("%f", &A); d =(float) sqrt((double)4*A/PI); printf("Der Durchmesser des Kreises ist %f\n", d);} empty circle(empty) { float U, d; printf("Geben Sie den Durchmesser des Kreises ein: "); scan("%f", &d); U = d*PI; printf("Der Umfang des Kreises ist %f\n", U);}void d2perimeter(void) { float U,d; printf("Geben Sie den Umfang des Kreises ein: "); scan("%f",&U); d = U/PI; printf("Der Durchmesser des Kreises ist %f\n", d);}int main(void) { circlearea(); Durchmesser(); Umfang(); d2scope(); gibt EXIT_SUCCESS zurück;}

In diesem Programm werden einfache Berechnungen von Kreisflächen durchgeführt. Eher, alsPiAn jeder Programmstelle neu zu definieren ist die textuelle Ersetzung mitdefinierenam besten geeignet. Dadurch wird auch sichergestellt, dass im gesamten Programm immer derselbe Wert verwendet wird. Ja. B. eine genauere Angabe vonPiSie brauchen nur die symbolische Konstante zu ändern.

Ein weiterer Vorteil ist z. B. die Verwendung bestimmter Konstanten, beispielsweise einer Landeswährung. Ist eine Änderung erforderlich, kann diese ohne großen Aufwand an einer Stelle für das gesamte Programm vorgenommen werden. Sie können auch vordefinierte Namen für Makrodefinitionen verwenden, wie im folgenden Beispiel:

#define PI 3.141592653#define PI_2 PI*2

hier kommt zuerstPidefiniert und in der nächsten Zeile der Wert vonIP*2, die lyrisch durchPI_2Es wird ersetzt.


Spitze

Verzichten Sie bei textuellen Ersetzungen auf überflüssige Berechnungen. Beispielsweise eine Typdefinition#definieren Pi für (1)*4dass dieser Wert im Programm jedes Mal neu berechnet wird. Verwenden Sie für solche Fälle besser einen.Konstante-Variablen wie:

Konstante doppelt Pi = für (1)*4;

Mit ihm#definierenDirektive können nicht nur Zahlen als symbolische Konstanten angegeben werden, sondern auch Strings. Beispiel:

#include <stdio.h>#define INT int#define WRITE printf(#define END );#define INPUT scanf(#define END START return 0;#define NEWLINE printf("\n");#define START int main( ) #define BEGIN ANFANG {#define BLOCO END }

Mit diesen Definitionen wurde mit minimalem Aufwand eine eigene kleine Programmiersprache geschaffen! Ein Programm in der neuen Sprache könnte beispielsweise so aussehen:

BEGIN BEGIN BEGIN Zahl INT; WRITE "Hallo Welt" END NEWLINE WRITE "Nummer eingefügt: " END INPUT "%d", &Nummer END WRITE "Oder Nummer war %d", Nummer END ENDSTARTBLOCKEND

Eine neue Programmiersprache wurde hier nicht wirklich geschaffen. Eher, alsint-Prinzipal()Es ist einfach im ProgrammANFANGgeschrieben, oder stattdessen0 zurückgebenWilleENDE ANFANGgeschrieben. Der Präprozessor ersetzt die Pseudosprache durch C, bevor der Compiler sie übersetzt.

Diese Pseudosprache muss nun in eine eigene Header-Datei gepackt werden. Erstellen Sie dazu eine neue Quelldatei mit folgendem Inhalt:

/* mysyntax.h */#ifndef MYSYNTAX_H#define MYSYNTAX_H#include <stdio.h>#include <stdlib.h>#define INT#define WRITE printf(#define END);#define INPUT scanf(#define ENDSTART return EXIT_SUCCESS ;#define NEWLINE printf("\n");#define START int main()#define BLOCK START {#define BLOCK END }#endif /*MYSYNTAX_H*/

Speichern Sie diese Codezeilen mit dem NamenMISINTAXIS.H. Nun folgt das Hauptprogramm inklusive der neuen Header-Datei:

/* my_C.c */#include "mysyntax.h"START BEGIN BLOCK INT Zahl; WRITE "Hallo Welt" END NEWLINE WRITE "Zahleneingabe: " END INPUT "%d", &Zahl END WRITE "Zahl war %d", Zahl END NEWLINE ENDSTART BLOCKEND

Speichern Sie das Hauptprogramm im selben Verzeichnis wie diemisintaxis.hgelegen. Den Namen des Hauptprogramms können Sie frei wählen, zum Beispiel:mi_c.c. Übersetzen Sie dieses Programm. Die Header-Datei befindet sichmisintaxis.hin einem anderen Verzeichnis als das Hauptprogramm, muss der Compiler darüber informiert werden. Ist die Header-Datei, zum Beispiel Sou/home/myhome/myheader, wird dies dem Präprozessor wie folgt gemeldet:

#include "/home/myhome/myheader/mysyntax.h"

Auf MS Windows-Systemen sollte es so aussehen (C:\sei deine Arbeitseinheit):

#include "c:\Programa\mysyntax.h"

10.2.2Makros com "#define" Rheinwerk Computing :: C von A bis Z - 10.2 Makros und Konstanten – »#define« (8)

Sie haben auch die Möglichkeit, diedefinieren-Anweisung zum Schreiben von parametrisierten Makros. Ein Beispiel:

/* define2.c */#include <stdio.h>#include <stdlib.h>#define SMALL_100(x) ((x) < 100)void klHundred(int number) { if(SMALL_100(number)) printf( "Ja! Die Zahl ist kleiner als 100!\n"); else printf("Die Zahl ist größer als 100!\n");}int main(void) { int b = 99; Klcien(b); gibt EXIT_SUCCESS zurück;}

Ein parametrisiertes Makro erkennen Sie an den eckigen Klammern direkt hinter dem Makronamen:

#define KLEINER_100(x) ((x) < 100)

Eigenständige Makros benötigen kein Semikolon am Zeilenende, wenn sie im Programm verwendet werden. Makros sind oft daran zu erkennen. Der Compiler wird sich nicht beschweren, wenn Sie trotzdem Semikolons setzen; aber es ist nicht zwingend.

Im betrachteten Fall hat es den formalen ParameterX.Dies kann auf der rechten Seite des Makros beliebig oft verwendet werden. Zu beachten ist, dass dieser Formalparameter auch auf der rechten Seite in Klammern eingeschlossen werden muss. Folgende Definition wäre falsch:

#define KLEINER_100(x) (x < 100)

da hier der parameterxnicht in Klammern. die Linie

se(MINOR_100(Zahl))

Nach der Ausführung des Präprozessors, also vor der eigentlichen Kompilierung, sieht es so aus:

wenn ((Zahl) < 100)

Eine weitere häufig verwendete Variante dieser Art ist:

#define MAX(x,y) ( (x)<=(y) ?(y) :(x) )

Hier werden zwei Argumente als Parameter verwendet. Beide Parameter werden durch ein Komma voneinander getrennt. Mit diesem Makro wird die größere von zwei Dezimalzahlen ermittelt. Ein anderes Beispiel:

#define TAUSCHE(x,y) { \ int j; \j=x; x=y; y=j; \ }

Dieses Makro vertauscht zwei ganzzahlige Werte. Dieses Beispiel zeigt auch, wie sich ein Makro mit mehreren Anweisungen über mehrere Zeilen erstrecken kann. Am Ende jeder Zeile der Makrodefinition muss ein Backslash stehen.

Lange Makros, auf die häufig zugegriffen wird, können Ihren Code jedoch unnötig überladen. In diesem Fall sind Rollen besser geeignet. Ein negatives Beispiel:

/* bad_define1.c */#include <stdio.h>#include <stdlib.h>#define MUCH_TEXT "TextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText\n"int main(void) { printf(MUCH_TEXT ); printf(MUCHO_TEXTO); printf(MUCHO_TEXTO); desenvolver EXIT_SUCCESS;}

Dieses Programm würde so aussehen, nachdem der Präprozessor ausgeführt wurde und bevor der Compiler ausgeführt wurde:

/* bad_define2.c */#include <stdio.h>#include <stdlib.h>int main(void) { printf("TextTextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextText"\ "TextTextTextTextTextText"); printf("TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText\n"); printf("TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText\n"); desenvolver EXIT_SUCCESS;}

Nun das gleiche Beispiel mit einer Funktion, die in diesem Fall die effizienteste Methode ist:

/* sin_define.c */#include <stdio.h>#include <stdlib.h>void lot_text(void) { printf("TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextTextTextText"\ "TextTextTextTextTextTextText}Text); principal (vacío ) { mucho_texto (); mucho_texto(); mucho_texto(); deve ser EXIT_SUCCESS;}

sterbendefinieren-directive ist eine ausschließlich für die Programmiersprache C vorgesehene Direktive, ein reiner C++-Compilerdefinierendaher wird es nicht erkannt und kompiliert. Die meisten Compiler kennen jedoch C und C++.

Im Allgemeinen sollten während der Kompilierung keine Probleme auftreten. Dies ist nur ein Plugin für das Thema, wenn Sie die Grundlagen von C lernen und dann zu C++ wechseln möchten. Kleinere Funktionsmakros können auch mit C++ und dem neuen Standard ANSI C99 arbeitenin der Reihe-Funktionen werden ersetzt.


realisieren

Der Geltungsbereich von symbolischen Konstanten oder Makros erstreckt sich ab dem Deklarationspunkt#definierenbis auf Widerruf#undef. Kündigung durch#undefaber es ist optional. Wille#undefnicht verwendet wird, wird der Gültigkeitsbereich bis zum Ende der Datei erweitert.

deine Meinung

Was haltet ihr von dem offenen Buch? Wir freuen uns immer über Ihre Kommentare. Bitte zögern Sie nicht, uns Ihre Kommentare per E-Mail zu senden.kommunikation@rheinwerk-verlag.de.

Top Articles
Latest Posts
Article information

Author: Geoffrey Lueilwitz

Last Updated: 03/08/2023

Views: 5675

Rating: 5 / 5 (80 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Geoffrey Lueilwitz

Birthday: 1997-03-23

Address: 74183 Thomas Course, Port Micheal, OK 55446-1529

Phone: +13408645881558

Job: Global Representative

Hobby: Sailing, Vehicle restoration, Rowing, Ghost hunting, Scrapbooking, Rugby, Board sports

Introduction: My name is Geoffrey Lueilwitz, I am a zealous, encouraging, sparkling, enchanting, graceful, faithful, nice person who loves writing and wants to share my knowledge and understanding with you.