Ich habe ein Makro, WW
, mit der Wortbreite in Bits, wie
Ich möchte einen neuen Typ, foo_t
, als Alias für eines der uintX_t
in <stdint.h>
deklarieren. Ich kann die Wortbreite hart codieren und
Allerdings ist uint(WW)
offensichtlich ein Fehler. Ich habe eine Weile mit einem Makro wie #define expand(x) x
herumgespielt und nutze es auf verschiedene Arten, ohne Erfolg. Mein letzter Ausweg ist eine #if
-Kaskade wie
was ich lieber vermeiden würde. Gibt es eine Möglichkeit, einen Typ basierend auf meinem Makro WW
zu schreiben, so dass uint(WW)
schließlich auf uint64_t
expandiert? Ich glaube, die Antwort ist "nein", aber einige Sprachanwälte beweisen mir bitte das Gegenteil.
Aufgrund der Art und Weise, wie die Makroerweiterung funktioniert, benötigen Sie eine zusätzliche Indirektionsebene:
%Vor%Von C11dr n1570:
6.10.3.1 Argumentsubstitution
Nachdem die Argumente für den Aufruf eines funktionsähnlichen Makros identifiziert wurden, Argumentsubstitution findet statt. Ein Parameter in der Ersetzungsliste, sofern nicht vorangestellt durch ein
#
oder##
Vorverarbeitungstoken oder gefolgt von einem##
Vorverarbeitungstoken (siehe unten), ist ersetzt durch das entsprechende Argument, nachdem alle darin enthaltenen Makros gefunden wurden erweitert. Bevor sie ersetzt werden, sind die Vorverarbeitungstoken jedes Arguments vollständig Makro ersetzt, als ob sie den Rest der Preprocessing-Datei gebildet hätten; kein anderer Vorverarbeitungstoken sind verfügbar.
Grundsätzlich müssen Sie die Erweiterung über ein Aufrufmakro durchführen:
%Vor%führt zu
%Vor% Im Falle von expand(uint_(WW))
wird es auf sein einziges Argument erweitert, was bedeutet, dass expand(uint_(WW))
zu uint_(WW)
wird. Da es Teil eines einzelnen Vorverarbeitungstokens ist, wird WW
nicht erweitert. Aus diesem Grund könnten Sie expand(expand(expand(uint_(WW))))
haben, und es würde immer noch nicht funktionieren.
Bei uint(WW)
wird es auf uint_(WW)
erweitert. Der obige Absatz besagt jedoch, dass das Argument für uint
einem Makroersatz unterliegt, also ist das Ergebnis tatsächlich uint_(<expansion of WW>)
, weil das Argument WW
Makro ersetzt wird. Das Makro uint_
wird dann mit dem ersetzten Wert von WW
aufgerufen.
Der Grund dafür, dass WW
direkt an das für typedef
verantwortliche Makro übergeben wurde, ist nicht der Fall, weil WW
Teil eines Ausdrucks ist, in den Token eingefügt werden ( ##
). "Ein Parameter in der Ersetzungsliste wird ersetzt, es sei denn, ihm wird ein #
oder ##
Vorverarbeitungstoken oder ein ##
Vorverarbeitungstoken vorangestellt ..." ersetzt. "Dies bedeutet im Wesentlichen, dass ##
die Expansion verhindert.
Sie können uint_(expand(WW))
nicht aus dem gleichen Grund verwenden: typedef uintexpand(WW)_t foo_t
sieht nicht genau richtig aus, oder?
Sie können dies auch über ein allgemeineres PASTE3
-Makro erreichen:
Denken Sie auch daran, dass WW
ein eigenständiger Ausdruck ist und vollständig durch Makros ersetzt wird. Dies bedeutet, dass unabhängig davon, wie viele Ebenen der Ersetzung vorhanden ist, diese erweitert wird, es sei denn, #
oder ##
stoppt die Erweiterung des Kurses:
ergibt:
%Vor%Tags und Links macros c language-lawyer