Eine bekannte und portable Möglichkeit, C-Compiler-Warnungen über nicht verwendete Variablen zu unterdrücken, ist (siehe Warnungen zu nicht verwendeten Parametern in C-Code):
#define UNUSED(x) (void)(x)
Ich suche nach einer Möglichkeit, dies zu verallgemeinern, um mehrere Eingaben (unterschiedlicher Art) zu verwenden:
Eine Möglichkeit, die den Trick zu machen scheint, ist die Verwendung einer variadischen Funktion
static inline void ALL_UNUSED(int dummy, ...) {}
Ich vermute jedoch, dass diese Lösung in Fachkreisen zu beanstanden ist.
Gibt es eine standardkonforme und portable (also nicht zu verwendende __attribute__((unused))) Möglichkeit, eine variadische UNUSED()-Funktion/Makro zu erstellen? Danke vielmals!
BEARBEITEN
Es scheint keinen sauberen Weg zu geben, das zu tun, worum ich im Zusammenhang mit C99 oder dem C-Präprozessor gebeten habe. So ist das Leben.
In seiner Antwort unten zeigt @Dabo eine ziemlich interessante Möglichkeit, das zu tun, worum ich gebeten habe, indem ich eine Reihe von Makros verwende. Das ist ordentlich und informativ (zumindest für mich), also akzeptiere ich diese Antwort. Das heißt, ich würde es nicht in einem großen Projekt einsetzen, weil es Tränen genug ist, um den Nutzen zu überwiegen, den es (in meinen Augen) bringt. Aber die Leute werden hier zu anderen Schlüssen kommen.
Wie unten angemerkt, ist der Ansatz, eine leere variadische Funktion zu verwenden, ebenfalls nicht perfekt. Obwohl es ein ziemlich eleganter Einzeiler ist, wird es Warnungen über unititialisierte Variablen provozieren (falls dies der Fall ist). Außerdem müssen Sie Ihrem Compiler vertrauen, dass er ihn vollständig wegoptimiert, was ich grundsätzlich ablehne, aber dass alle Compiler, mit denen ich es versucht habe, dies tatsächlich tun.
Ein relevanter Fall ist das Stubben von Funktionen nach einer frühen High-Level-Schnittstellendesignphase. Dann sind Ihre nicht verwendeten Variablen alle Funktionsargumente und per Definition initialisiert, und der folgende Ansatz funktioniert gut
static inline void UNUSED(int dummy, ...) {}
void foo(int a, long b, void* c){
UNUSED(a, b, b); /* No warnings */
}
Was ist mit der Verwendung #define UNUSED(...) (void)(__VA_ARGS__).
– Mach dir keine Sorgen, Kind
23. April 2014 um 5:59 Uhr
Leider nein – probiert. Der Compiler warnt vor einem unbenutzten Ausdrucksergebnis oder einem “Wert als Anweisung”. Was erwarten Sie semantisch (void) (a, b, c); meinen?
– Tag
23. April 2014 um 6:07 Uhr
Danke für den Hinweis. Versuche es mal anders…
– Mach dir keine Sorgen, Kind
23. April 2014 um 6:10 Uhr
Beachten Sie, dass gcc die Option hat -Wno-unused-variable was scheint zu tun, was du fragst? Obwohl sich die Frage vielleicht eher um Varadics und Makros dreht …
– spinus
23. April 2014 um 7:20 Uhr
#define UNUSED(x) (void)(x) eigentlich bewertet ‘x’ … #define UNUSED(x) (void)(sizeof(x)) ist auch keine perfekte Lösung, da C99 berühmte VLAs (Variable Length Arrays) eingeführt hat, die auch ausgewertet werden, wenn sie an die übergeben werden sizeof() …
Wie für inline Methode, die Sie gepostet haben, ein Schnelltest
int a=0;
long f,d;
ALL_UNUSEDINLINE(a,f,&d);
gibt ‘f’ is used uninitialized in this function [-Wuninitialized] Warnung. Hier also zumindest ein Anwendungsfall, der die Allgemeingültigkeit dieses Ansatzes bricht
Ganz nett! Ich werde damit herumspielen und sehen, wie es sich anfühlt. Die manuelle Aufzählung scheint unvermeidlich, macht aber kaum jemanden zum Verlieben in cpp. Vielen Dank!
– Tag
23. April 2014 um 8:38 Uhr
Darf ich fragen, was Sie von dem Void-Variadic-Funktionsansatz halten, den ich in dem Beitrag erwähne (der etwas kürzer ist als Ihre beeindruckende Makrolösung)? Erscheint es Ihnen falsch und/oder fehlerhaft?
– Tag
23. April 2014 um 8:42 Uhr
@dag siehe mein edit2 bzgl inlineich nehme an, es beantwortet Ihre Frage.
– Dabu
23. April 2014 um 11:12 Uhr
Danke für den Hinweis! Der (nicht angegebene) Anwendungsfall, den ich im Sinn hatte, bestand eigentlich nur darin, Warnungen von nicht verwendeten Funktionsargumenten zu unterdrücken.
– Tag
25. April 2014 um 4:12 Uhr
Kugel
Ich habe die großartige Lösung von Dabo (https://stackoverflow.com/a/23238813/5126486) genommen und ein wenig verbessert, damit es einfacher ist, sie auf mehr als 5 zu erweitern:
Führt zu “Warnung: Ausdrucksergebnis nicht verwendet”, aber dies kann leicht behoben werden
– Simon Warta
16. April 2017 um 20:05 Uhr
+1 Kommentar für user824425 und -1 Antwort für Gian Lorenzo Meocci. Die Frage bezieht sich auf C. Wenn es C++ wäre, können Sie die Argumentnamen einfach weglassen (aber die Typen belassen).
– Herr Stobbe
20. April 2019 um 7:00 Uhr
Das Lambda erfordert, dass die Objekte kopierbar sind.
– HolyBlackCat
22. April 2021 um 5:41 Uhr
Matt Eding
Hier ist ein sehr einfacher Ansatz, der keine besonderen Tricks erfordert und auch keinen Laufzeit-Overhead verursacht.
Ich hatte vergessen, den Compiler von C++ auf C umzustellen, und daher die überarbeitete Antwort.
int main(int argc, char ** argv)
{
/* different types */
UNUSED(argc, argv);
/* many variables */
int w, x, y, z;
UNUSED(w, x, y, z);
/* single variable */
void * ptr;
UNUSED(ptr);
}
MSVC
/O2 /W4
Keine Warnungen von C- und C++-Compilern.
Klirren
-O3 -Wand -Wextra
Keine Warnungen von C- und C++-Compilern.
GCC
-O3 -Wand -Wextra
Keine Warnungen nur vom C++-Compiler. Beim C-Compiler wird nur der letzte Parameter ohne Warnung ignoriert. Also im schlimmsten Fall diese Version von UNUSED ist dem traditionellen ebenbürtig #define UNUSED(x) ((void)x).
Das Folgende verursacht keine Warnungen mit -Wall -Wextra auf GCC und Clang, funktioniert aber nur für C11 und höher:
Das hängt von den Typen der übergebenen Parameter ab, nicht wahr? Sie haben möglicherweise nicht die gleichen und kompatiblen Typen, die als Initialisierer für das Array zulässig sind, was zu einer weiteren Warnung oder sogar zu Fehlern führt, z. Warum würde dies auch C11 erfordern?
– stefankt
23. September um 22:19 Uhr
Ich bekomme diesen Fehler nicht mit String-Literalen, aber ja, das funktioniert nur für einige Typen, da Struct- und Union-Typen nicht konvertierbar sind _Bool, also müssen Sie die Adresse von Variablen mit diesen Typen nehmen. Das Makro erfordert C11, da zusammengesetzte Literale ((_Bool[]){__VA_ARGS__}) in C11 hinzugefügt wurden, wenn Ihr Projekt C11 (oder höher) nicht verwendet, müssen Sie auf eine weniger minimale Lösung zurückgreifen. Ich mag diese Lösung, weil alle meine Projekte C11 sind und weil unbenutzte Strukturen und Vereinigungen (keine Zeiger) sehr selten sind.
– yyny
28. September um 15:26 Uhr
Zusammengesetzte Literale wurden in C99 hinzugefügt.
– stefankt
29. September um 16:08 Uhr
vjalle
Eine etwas verfeinerte Version der Lösung in der Frage, die jede Art von Argumenten akzeptiert:
Scheint mit mehreren Compilern zu arbeiten, nicht nur mit GCC.
Das hängt von den Typen der übergebenen Parameter ab, nicht wahr? Sie haben möglicherweise nicht die gleichen und kompatiblen Typen, die als Initialisierer für das Array zulässig sind, was zu einer weiteren Warnung oder sogar zu Fehlern führt, z. Warum würde dies auch C11 erfordern?
– stefankt
23. September um 22:19 Uhr
Ich bekomme diesen Fehler nicht mit String-Literalen, aber ja, das funktioniert nur für einige Typen, da Struct- und Union-Typen nicht konvertierbar sind _Bool, also müssen Sie die Adresse von Variablen mit diesen Typen nehmen. Das Makro erfordert C11, da zusammengesetzte Literale ((_Bool[]){__VA_ARGS__}) in C11 hinzugefügt wurden, wenn Ihr Projekt C11 (oder höher) nicht verwendet, müssen Sie auf eine weniger minimale Lösung zurückgreifen. Ich mag diese Lösung, weil alle meine Projekte C11 sind und weil unbenutzte Strukturen und Vereinigungen (keine Zeiger) sehr selten sind.
– yyny
28. September um 15:26 Uhr
Zusammengesetzte Literale wurden in C99 hinzugefügt.
– stefankt
29. September um 16:08 Uhr
Sie können die Kompilierzeit verwenden __VA_ARGS__ Makro.
#define UNUSED(...) (void)(__VA_ARGS__)
AKTUALISIEREN: Nach vielen Versuchen bin ich zu einer optimierten Lösung gekommen:
#define UNUSED(...) __VA_ARGS__
int main()
{
int e, x;
char **a, **b, *c, d[45];
x = x, UNUSED(a, b, c, d, e), x;
return 0;
}
ANMERKUNGEN:
Es eliminiert Warnungen nicht vollständig, aber reduziert sie nur 3 Gleiche Art von Warnungen: warning: value computed is not used
Der erste und der letzte x Zuweisung gleicher Datentypen sicherstellen.
Ich werde sagen, es ist optimiert, weil es für eine beliebige Anzahl von unbenutzten Variablen gibt 3 Warnungen (ich kann mich irren, bitte testen Sie es selbst und melden Sie mich, wenn Sie mehr erhalten) und die Menge an Code (MACRO-Manipulationen), die erforderlich ist, um dies zu erreichen, ist geringer.
Ich arbeite noch daran, werde posten, wenn ich zu einer besseren Lösung komme.
Danke @MadHatter, aber ich denke, sowohl Clang als auch GCC geben immer noch Warnungen damit aus. GCC “Warnung: linker Operand des Komma-Ausdrucks hat keine Wirkung [-Wunused-value]”, Clang: “Warnung: Ausdrucksergebnis ungenutzt [-Wunused-value]”
– Tag
23. April 2014 um 6:12 Uhr
Ja!! Ich habe es selbst mit zusammengestellt gcc -Wall und bekam dieselbe Warnung. Probiere noch was…
Was ist mit der Verwendung
#define UNUSED(...) (void)(__VA_ARGS__)
.– Mach dir keine Sorgen, Kind
23. April 2014 um 5:59 Uhr
Leider nein – probiert. Der Compiler warnt vor einem unbenutzten Ausdrucksergebnis oder einem “Wert als Anweisung”. Was erwarten Sie semantisch (void) (a, b, c); meinen?
– Tag
23. April 2014 um 6:07 Uhr
Danke für den Hinweis. Versuche es mal anders…
– Mach dir keine Sorgen, Kind
23. April 2014 um 6:10 Uhr
Beachten Sie, dass gcc die Option hat
-Wno-unused-variable
was scheint zu tun, was du fragst? Obwohl sich die Frage vielleicht eher um Varadics und Makros dreht …– spinus
23. April 2014 um 7:20 Uhr
#define UNUSED(x) (void)(x)
eigentlich bewertet ‘x’ …#define UNUSED(x) (void)(sizeof(x))
ist auch keine perfekte Lösung, da C99 berühmte VLAs (Variable Length Arrays) eingeführt hat, die auch ausgewertet werden, wenn sie an die übergeben werdensizeof()
…– Benutzer10133158
12. September 2018 um 10:52 Uhr