Ich habe ein Makro definiert. Aber ich muss diesen Wert zur Laufzeit abhängig von einer Bedingung ändern. Wie kann ich das umsetzen?
Ändern eines Makros zur Laufzeit in C
Leuchtturm
fbrereto
Makros werden vom Präprozessor durch ihren Wert ersetzt, bevor Ihre Quelldatei überhaupt kompiliert wird. Es gibt keine Möglichkeit, den Wert des Makros zur Laufzeit zu ändern.
Wenn Sie etwas mehr über das Ziel erklären könnten, das Sie erreichen möchten, gibt es zweifellos eine andere Möglichkeit, Ihr Problem zu lösen, die keine Makros enthält.
-
Was ist, wenn das Makro einer Funktion zugewiesen wird, die über die Logik verfügt, um den gewünschten Wert zu erhalten, und zurückgibt? Wäre das Makro dann nicht in der Lage, einen dynamischen Wert zurückzugeben?
– Hartes S.
30. Januar 2019 um 5:24 Uhr
-
@HarshS. Wenn das Makro in eine Funktion aufgelöst wird, ersetzt der Präprozessor das Makro durch den Namen der Funktion, bevor die C++-Datei kompiliert wird. Das Makro selbst wird dabei nicht “dynamisch”. Vielmehr ist das Ding, in das das Makro aufgelöst wird, ein Ding, das einen Laufzeitwert zurückgibt.
– fbrereto
31. Januar 2019 um 19:50 Uhr
Steve Jessop
Sie können das Makro selbst nicht ändern, dh worauf es erweitert wird, aber möglicherweise können Sie den Wert von an ändern Ausdruck unter Einbeziehung des Makros. Für ein sehr dummes Beispiel:
#include <stdio.h>
#define UNCHANGEABLE_VALUE 5
#define CHANGEABLE_VALUE foo
int foo = 5;
int main() {
printf("%d %d\n", UNCHANGEABLE_VALUE, CHANGEABLE_VALUE);
CHANGEABLE_VALUE = 10;
printf("%d %d\n", UNCHANGEABLE_VALUE, CHANGEABLE_VALUE);
}
Die Antwort auf Ihre Frage hängt also davon ab, welche Auswirkungen Ihre Änderung auf den Code haben soll, der das Makro verwendet.
Na sicher 5
ist eine Kompilierzeitkonstante, während foo
ist nicht, also funktioniert dies nicht, wenn Sie es verwenden möchten CHANGEABLE_VALUE
Als ein case
Etikett oder was auch immer.
Denken Sie daran, dass es zwei (eigentlich mehr) Phasen der Übersetzung der C-Quelle gibt. Im ersten (von den beiden, die uns wichtig sind) werden Makros erweitert. Wenn das alles erledigt ist, wird das Programm “syntaktisch und semantisch analysiert”, wie es in 5.1.1.2/2 heißt. Diese beiden Schritte werden oft als „Vorverarbeitung“ und „Kompilierung“ bezeichnet (obwohl mehrdeutig oft auch der gesamte Übersetzungsprozess als „Kompilierung“ bezeichnet wird). Sie können sogar durch separate Programme implementiert werden, wobei der “Compiler” den “Präprozessor” nach Bedarf ausführt, bevor er irgendetwas anderes tut. Die Laufzeit ist also viel, viel zu spät, um zu versuchen, zurückzugehen und zu ändern, worauf ein Makro erweitert wird.
-
hmm .. diese Antwort besagt, dass Sie ein Makro als Fallbezeichnung verwenden können: stackoverflow.com/questions/1674032/static-const-vs-define-in-c/…
– Benutzer195488
27. September 2011 um 17:34 Uhr
-
@0A0D: Es heißt: “Sie können kein const int-Objekt als Case-Label verwenden (während ein Makro funktioniert)”. Das soll das nicht bedeuten irgendein Makro ist eine Bezeichnung für Rechtsfälle, oder dass Sie mit einem Makro auf magische Weise Dinge in Fallbezeichnungen verwenden können, die Sie sonst nicht könnten. AndreyT vergleicht
const int
Objekte mit Makros als Integer-Literale definiert.case UNCHANGEABLE_VALUE:
ist in Ordnung,case CHANGEABLE_VALUE:
ist nicht.– Steve Jessop
27. September 2011 um 17:43 Uhr
Du kannst nicht. Makros werden um die erweitert Präprozessor, was noch vor dem Kompilieren des Codes geschieht. Es ist ein rein textlicher Ersatz.
Wenn Sie zur Laufzeit etwas ändern müssen, ersetzen Sie einfach Ihr Makro durch einen echten Funktionsaufruf.
-
Könnten Sie bitte ein einfaches Beispiel geben, wie Sie es durch einen Funktionsaufruf ersetzen können?
– utvecklare
11. September 2013 um 11:25 Uhr
Du kannst nicht.
Da ein Makro vom Präprozessor vor der Kompilierung selbst aufgelöst wird, wird sein Inhalt direkt dorthin kopiert, wo Sie ihn verwenden.
Sie können weiterhin Parameter verwenden, um je nach Wunsch eine bedingte Anweisung einzufügen, oder eine im Aufrufbereich zugängliche Variable verwenden.
Wenn Sie einen einzelnen Wert ändern möchten, verwenden Sie besser eine globale Bereichsvariable, auch wenn von einem solchen Verhalten abgeraten wird. (wie die intensive Verwendung von Makro)
Je nachdem, was Sie tun möchten, können Sie dies auf verschiedene Arten tun.
Globale Variable statt Makro
// someincludefile.h
extern static int foo;
// someincludefile.c
static int foo = 5;
// someotherfile.c
#include "someincludefile.h"
printf("%d\n", foo); // >> 5
foo = -5;
printf("%d\n", foo); // >> -5
Bedingung, die Sie umschalten können
// someincludefile.h
extern static int condition;
#define FOO1 (5)
#define FOO2 (-5)
#define FOO (condition ? (FOO1) : (FOO2))
// someincludefile.c
static int condition = 1;
// someotherfile.c
#include "someincludefile.h"
printf("%d\n", FOO); // >> 5
condition = 0;
printf("%d\n", FOO); // >> -5
Bedingung, die lokal und dynamisch ausgewertet wird
// someincludefile.h
#define CONDITION (bar >= 0)
#define FOO1 (5)
#define FOO2 (-5)
#define FOO ((CONDITION) ? (FOO1) : (FOO2))
// someotherfile.c
#include "someincludefile.h"
int bar = 1;
printf("%d\n", FOO); // >> 5
bar = -1;
printf("%d\n", FOO); // >> -5
In letzterem wird die BEDINGUNG so ausgewertet, als wäre ihr Code in Ihrem lokalen Gültigkeitsbereich, sodass Sie darin lokale Variablen und/oder Parameter verwenden können, aber Sie können auch globale Variablen verwenden, wenn Sie möchten.
Makros durchlaufen den Präprozessor. Sie können während der Laufzeit nicht geändert werden. Ist dies eine Makrokonstante oder ein Funktionsmakro, das ein Argument akzeptiert?
– Benutzer195488
27. September 2011 um 16:58 Uhr
Übrigens, diese Frage ist gut, also können wir sie auf Stackoverflow mit “nein” beantworten.
– Prof. Falken
27. September 2011 um 17:03 Uhr
Könnten Sie bitte ein Beispiel für Ihr Makro geben – es scheint mir, dass Sie nicht wirklich ein runtime-updateable-macro benötigen, was keinen Sinn ergibt – sondern ein Makro mit einem oder mehreren zusätzlichen Parametern. Oder vielleicht überarbeiten Sie Ihren Code trotzdem ..
– rudolf_franek
27. September 2011 um 17:14 Uhr
# definiere SIZE 100 und in dem Code, den du verwenden möchtest, sollte es in einigen Fällen 50 sein. Was wird dann mein Schritt sein? Weil ich eine Menüliste in Abhängigkeit von der GRÖSSE erstellen möchte. if(something) then create 50 menu else create SIZE menu Derzeit habe ich nur eine Variable erstellt und den Variablenwert abhängig von der Bedingung geändert, während er zuvor vom Marco aktualisiert wurde.
– Leuchtturm
27. September 2011 um 17:19 Uhr
@lighthouse, Variablen sind dann der richtige Weg.
– Prof. Falken
27. September 2011 um 20:08 Uhr