Zeiger auf Literalwert
Nehme an, dass ich eine Konstante definiert, die in einer header-Datei
#define THIS_CONST 'A'
Ich schreiben wollen diese Konstante in einem stream. Ich Tue so etwas wie:
char c = THIS_CONST;
write(fd, &c, sizeof(c))
Jedoch, was würde ich wie zu tun, für die Kürze und Klarheit ist:
write(fd, &THIS_CONST, sizeof(char)); //error
//lvalue required as unary ‘&’ operand
Kennt jemand eine makro/anderen trick für das erhalten einen Zeiger auf ein literal? Ich möchte etwas, das kann z.B. so verwendet werden:
write(fd, PTR_TO(THIS_CONST), sizeof(char))
Hinweis: ich begreife, dass ich könnte, erkläre meine Konstanten static const Variablen, aber dann kann ich Sie nicht benutzen in der switch/case-Anweisungen. also
static const char THIS_CONST = 'A'
...
switch(c) {
case THIS_CONST: //error - case label does not reduce to an integer constant
...
}
Es sei denn, es ist ein Weg, um eine const-variable in einer case-Bezeichnung?
- Die einzige Sache, die Federn in den Sinn ist ein linker trick. Welchen compiler benutzt du? Wenn Sie sich vorstellen können, etwas absolute pointer-Werte in Ihren linker-Befehle, die Sie nutzen könnten, z.B., (void *)0 x 00000004, als ein integer-Wert '4' und auch als Charakter. Es ist nicht portable. Wenn Sie am Fenster, schauen in die C++ - Konstruktor Liste benannt .cxa - .cxz verwendet, die von der MS-Visual-C standard-C-Bibliothek, die während der Initialisierung. Das ist ähnlich der Art von linker trick, den ich spreche. Der Unterschied wäre, wodurch das Bild enthalten einige non-relocatable Adressen, die Sie werfen kann, um int.;)
- Interessante Idee - das ist ein wenig mehr Schädel duggery, als ich suchte, aber trotzdem interessant. Ich bin mit gcc und meinen code zu kompilieren unter Linux und Solaris 🙂
- Abgesehen von zu wollen, um es in einer case-Anweisung, warum sonst brauchen Sie es? In einer Ihrer Antworten, die Sie sagte, Sie wollte auch es auch für Schwimmer, aber Sie können nicht verwenden Sie schweben wie eine case-Anweisung, Ausdruck sowieso.
- Guter Punkt, um Schwimmer -, sondern int-Werte immer noch gelten. Das müssen nur die, die ich habe, für die es in einer case-Anweisung. Aber diese Frage war motiviert, die nicht so viel von 'brauchen', aber nur wollen, um zu sehen, ob es möglich war, über einige C-Makros Tricks (und wohl wissend, dass ein literal ist nicht das gleiche wie eine variable und nicht Ihre Adresse). Jedenfalls danke Euch allen für Eure Beiträge - ich glaube, die kurze Antwort ist 'Nein', es gibt keine akzeptierten trick für das erhalten der compiler um ein literal mit dem Wert in einer Speicherstelle und erhalten einen Zeiger auf es, und keine " saubere & threadsicher sind Weg, es zu tun zur Laufzeit.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es keine Möglichkeit, dies direkt in C89. Sie müssten eine Reihe von Makros zum erstellen eines solchen Ausdrucks.
In C99 ist es erlaubt zu deklarieren struct-oder union-Literale und-Initialisierungen auf Skalare geschrieben werden können, mit einer ähnlichen syntax. Daher gibt es einen Weg, das zu erreichen den gewünschten Effekt:
Nur so erhalten Sie ein Zeiger ist, indem Sie das literal in eine variable (der erste code-Beispiel). Sie können dann verwenden Sie die variable mit
write()
und das literal inswitch
.C einfach nicht zulassen, dass die Adresse der Zeichen-Literale wie 'Ein'. Für was es Wert ist, den Typ von Zeichen-Literale in C ist int (char in C++, aber diese Frage ist tagged-C). 'A' wäre eine Implementierung definierten Wert (zum Beispiel 65 auf ASCII-Systemen). Unter der Adresse der Wert macht keinen Sinn und ist nicht möglich.
Nun, natürlich Sie kann nehmen Sie sich die Adresse von anderen Arten von literalen wie string-Literale, beispielsweise die folgenden ist okay:
Dies ist, weil das string-literal "Kartoffel" ist ein array, und sein Wert ist ein Zeiger auf die 'p' am Anfang.
Erarbeiten/klären, Sie dürfen nur die Adresse von Objekten. ie, die & (Adresse-von) operator benötigt ein Objekt, nicht einen Wert.
Und die Antwort auf die andere Frage, die ich verpasste, C erlauben keine nicht-Konstante case-Bezeichnungen, und dies beinhaltet auch die Variablen, die const.
'A'
ist nicht eine wörtliche, sondern eine Konstante. C hat 2 Arten von literalen: string-literal und compound-literal. Beide von diesen zwei kann Ihre Adresse aufgenommen, im Gegensatz zu Konstanten'A'
.Diese Antworten sind alle veraltet, und abgesehen von einem Kommentar niemand bezieht sich auf die jüngsten language updates.
Auf einen C99-C11-compiler mit einem compound-literal, http://en.cppreference.com/w/c/language/compound_literal, ist es möglich, zu erstellen
ein Zeiger auf einen namenlosen Konstanten, in:
Seit dem Aufruf write () - schreiben eines einzelnen Zeichens in eine Datei-Deskriptor ist fast sicher ein performance-killer, wahrscheinlich möchten Sie nur das zu tun, fputc( THIS_CONST, Bach ).
Ist nur ein makro. Der compiler grundsätzlich nur Einsätze " ein " überall verwenden Sie THIS_CONST.
Sie könnten versuchen:
Aber ich vermute, dass wird nicht funktionieren welken (nicht über einen c-compiler praktisch versuchen Sie es auf, und es ist jetzt schon einige Jahre her, seit ich geschrieben habe c-code).
const
bedeutet meist "readonly", und manchmal heißt "compile-time-literal-Konstante". In C, es ist immer das alte - einconst
variable ist read-only ab dem Zeitpunkt der Initialisierung, aber es ist keine Konstante zur Kompilierungszeit. Das ist der Grund, warum alle C-Bibliotheken verwenden#define
für echte Konstanten.verwenden Sie einfach eine string-Konstante, die einen Zeiger auf ein Zeichen, und dann nur schreiben, 1 byte:
Beachten Sie, dass das '\0' - byte an das Ende der Zeichenkette wird nicht geschrieben.
Können Sie dies tun, für alle Arten von Konstanten Werten, verwenden Sie einfach den entsprechenden hex-code der Zeichenfolge, z.B.
geben wird, auch die Zeichen 'A'. Für mehrere byte Zeug, aufpassen, dass Sie den korrekten endianness.
Lassen Sie uns sagen, Sie wollen, um einen Zeiger auf eine INT_MAX, welches z.B. 0x7FFFFFFF auf einem 32-bit-system. Dann können Sie Folgendes tun:
Können Sie sehen, dass dies funktioniert, indem Sie es als ein dereferenzierter Zeiger printf:
dem drucken sollten 2147483647.
(int*)PTR_TO_INT_MAX
hat 2 weitere Probleme. Casting zuint*
kann nicht befriedigen alignment-Anforderungen."\xFF\xFF\xFF\x7F"
ist endian empfindlich.Für chars, können Sie zusätzliche Globale statische Variablen. Vielleicht so etwas wie:
Gibt es keinen Grund, den compiler muss das literal in jeder Position im Speicher, so dass Ihre Frage keinen Sinn. Zum Beispiel eine Aussage wie
dann wahrscheinlich nur direkt übersetzt "einen Wert von zehn in ein register". In den Assembler-output des Compilers, der Wert zehn die sich selbst noch nie als etwas existiert, in der Erinnerung, die sein könnte, deutete an, es sei denn als Teil der eigentlichen Programm-text.
Können Sie nicht nehmen Sie einen Zeiger darauf.
Wenn Sie wirklich wollen, ein makro einen Zeiger,
Kann ich sehen, was Sie versuchen, hier zu tun, aber Sie versuchen, verwenden Sie zwei grundlegend verschiedene Dinge hier. Die Krux an der Sache ist, dass
case
- Anweisungen müssen Werte verwenden, die vorhanden sind, auf compile-Zeit, sondern Zeiger auf Daten im Speicher zur Verfügung stehen nur Laufzeit.Wenn Sie dies tun:
tun Sie zwei Dinge. Sie machen das makro
THIS_CONST
zur Verfügung, um den rest der code zur compile-Zeit, und erstellen Sie eine neuechar
zur Laufzeit die Initialisierung zu diesem Wert. An dem Punkt, an dem die Liniewrite(fd, &c, sizeof(c))
ausgeführt wird, wird das Konzept derTHIS_CONST
ist nicht mehr vorhanden, so haben Sie richtig erkannt, dass Sie können erstellen Sie einen Zeiger aufc
, aber nicht einen Zeiger aufTHIS_CONST
.Nun, wenn Sie dies tun:
static const char THIS_CONST = 'A';
switch(c) {
Fall THIS_CONST: //Fehler - Fall " - label lässt sich nicht reduzieren auf eine integer-Konstante
...
}
Sie code schreiben, bei denen der Wert der case-Anweisung muss zur Kompilierzeit ausgewertet. Aber in diesem Fall haben Sie angegeben
THIS_CONST
in einer Weise, wo es ist eine variable, und daher ist sein Wert ist nur zur Laufzeit obwohl Sie "wissen", dass es geht, um einen bestimmten Wert. Sicherlich, andere Sprachen können unterschiedliche Dinge geschehen, mit case-Anweisungen, aber das sind die Regeln mit C.Hier ist, was ich vorschlagen würde:
1) rufen Sie nicht eine variable
THIS_CONST
. Es gibt keinen technischen Grund, nicht zu, aber die Konvention legt nahe, dass dies während der Kompilierung makro, und Sie wollen nicht zu verwirren Ihre Leser.2) Wenn Sie möchten, dass die gleichen Werte zur Verfügung zu compile-Zeit und Laufzeit, finden Sie eine geeignete Möglichkeit, mapping-compile-Zeit-Makros in den run-Zeit-Variablen. Das kann gut sein, so einfach wie:
Dann kann tun:
(Beachten Sie auch, dass
sizeof(char)
ist immer eine, per definition. Sie wissen vielleicht, dass schon, aber es ist nicht so geschätzt, wie es vielleicht sein sollte.)Ok, ich habe ein bisschen ein hack, für chars nur - aber ich werde es hier zu setzen, um zu sehen, wenn es inspiriert jede bessere Lösungen von anderen
static char val
variable? Was war der Punkt der, dass statische array ist, können Sie das erklären?static char
würde bedeuten, dass diese Funktion würde immer wieder ein Zeiger auf die gleiche Position, die enthält den letzten Wert an diese Funktion übergeben. Re-Initialisierung den Wert bei jedem Anruf war um zu vermeiden, dass pre-füllen des Arrays.