Wie kann ich Warnungen vor nicht verwendeten Parametern in C unterdrücken?


210

Zum Beispiel:

Bool NullFunc(const struct timespec *when, const char *who)
{
   return TRUE;
}

In C ++ konnte ich /*...*/die Parameter kommentieren. Aber natürlich nicht in C, wo es mir den Fehler gibt error: parameter name omitted.



4
@CiroSantilli Diese Frage hat mehr positive Stimmen. Es ist besser, die andere Frage als Duplikat zu markieren.
Sashoalm


-Wno-unused-parameter, es ist einfach zu laut und fängt selten Fehler, insb. wann -Wshadowwird verwendet.
Trass3r

Antworten:


297

Normalerweise schreibe ich ein Makro wie folgt:

#define UNUSED(x) (void)(x)

Sie können dieses Makro für alle nicht verwendeten Parameter verwenden. (Beachten Sie, dass dies auf jedem Compiler funktioniert.)

Beispielsweise:

void f(int x) {
    UNUSED(x);
    ...
}

45
Ich benutze nur (void) x direkt
Prof. Falken

6
Dies ist zwar der einzige tragbare Weg für AFAIK, aber das Ärgernis dabei ist, dass es irreführend sein kann, wenn Sie die Variable später verwenden und vergessen, die nicht verwendete Zeile zu entfernen. Deshalb ist GCC's unbenutzt nett.
ideasman42

6
@CookSchelling: Ah, aber du solltest es nicht so benutzen. Mach so etwas : void f(int x) {UNUSED(x);}.
Job

9
@Alcott, weil (wie in meinem Fall) die Funktion möglicherweise eine von vielen ist, die dieselbe Signatur haben müssen, weil sie von einem Funktionszeiger referenziert werden.
Josch

17
Ich verwende #define UNUSED(...) (void)(__VA_ARGS__), wodurch ich dies auf mehrere Variablen anwenden kann.
Matthew Mitchell

110

In gcc können Sie den Parameter mit dem unusedAttribut kennzeichnen .

Dieses Attribut, das an eine Variable angehängt ist, bedeutet, dass die Variable möglicherweise nicht verwendet werden soll. GCC erzeugt keine Warnung für diese Variable.

In der Praxis wird dies erreicht, indem __attribute__ ((unused))direkt vor den Parameter gesetzt wird. Beispielsweise:

void foo(workerid_t workerId) { }

wird

void foo(__attribute__((unused)) workerid_t workerId) { }

24
Für Neulinge wie mich bedeutet dies, sich __attribute__ ((unused))dem Argument zu stellen.
Josch

2
@josch Ich denke, Sie sind völlig korrekt, aber die Dokumentation scheint zu implizieren, dass es nach dem Parameter gesetzt werden sollte. Beide Optionen werden wahrscheinlich problemlos unterstützt.
Antonio

Beachten Sie auch, dass __attribute__((unused))es sich um eine proprietäre GCC-Erweiterung handelt . Es wird von einigen anderen Compilern unterstützt, aber ich gehe davon aus, dass dies mit MSVC nicht funktioniert. Es ist jedoch nicht direkt Teil des Compiler-Standards, daher ist dies nicht so portabel wie einige andere Optionen
Zoe

58

Sie können das nicht verwendete Attribut von gcc / clang verwenden. Ich verwende diese Makros jedoch in einem Header, um zu vermeiden, dass gcc-spezifische Attribute in der gesamten Quelle vorhanden sind. Außerdem __attribute__ist es etwas ausführlich / hässlich , überall zu haben.

#ifdef __GNUC__
#  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#else
#  define UNUSED(x) UNUSED_ ## x
#endif

#ifdef __GNUC__
#  define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
#else
#  define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif

Dann können Sie tun ...

void foo(int UNUSED(bar)) { ... }

Ich bevorzuge dies, weil Sie eine Fehlermeldung erhalten, wenn Sie versuchen, zu verwenden bar den Code irgendwo zu verwenden, damit Sie das Attribut nicht versehentlich belassen können.

und für Funktionen ...

static void UNUSED_FUNCTION(foo)(int bar) { ... }

Anmerkung 1):
Soweit ich weiß, hat MSVC kein Äquivalent zu__attribute__((__unused__)) .

Hinweis 2):
Das UNUSEDMakro funktioniert nicht für Argumente, die Klammern enthalten.
Wenn Sie also ein Argument wie float (*coords)[3] Sie haben es nicht können,
float UNUSED((*coords)[3])oder float (*UNUSED(coords))[3]: Dies ist der einzige Nachteil des UNUSEDMakros, das ich bisher gefunden habe. In diesen Fällen greife ich zurück zu(void)coords;


Oder vielleicht nur #define __attribute__(x)für Nicht-GCC-Umgebungen (AFAIK keine __attribute__von MSVC unterstützt)?
Franklin Yu

Das kann funktionieren, aber dunder vorangestellte Begriffe sind für den Compiler reserviert, daher möchte ich dies lieber vermeiden.
ideasman42

Für meine gcc mindestens das Attribut Bezeichner setzen , bevor die Kennung an die Arbeit richtig für funcs scheint, VARs und Parameter, so etwas wie #define POSSIBLY_UNUSED (Identifier) Attribut __ ((__ ungenutzt )) Kennung kann für alle drei verwendet werden
Britton Krein

Wenn ich es warning: unused parameter ‘foo’ [-Wunused-parameter]setze , nachdem ich (gcc 7.3.0) bekommen habe
ideasman42

19

Mit gcc mit dem nicht verwendeten Attribut:

int foo (__attribute__((unused)) int bar) {
    return 0;
}

16

Da dies als gcc markiert ist, können Sie den Befehlszeilenschalter verwenden Wno-unused-parameter .

Beispielsweise:

gcc -Wno-unused-parameter test.c

Dies wirkt sich natürlich auf die gesamte Datei aus (und möglicherweise auf das Projekt, je nachdem, wo Sie den Schalter eingestellt haben), aber Sie müssen keinen Code ändern.


7

Eine gcc / g ++ - spezifische Möglichkeit, die nicht verwendete Parameterwarnung für einen Quellcodeblock zu unterdrücken, besteht darin, sie den folgenden Pragma-Anweisungen beizufügen:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
<code with unused parameters here>
#pragma GCC diagnostic pop

Clang unterstützt diese diagnostischen Pragmas auch clang.llvm.org/docs/…
eush77

4

Das Beschriften des Attributs ist ideal. MAKRO führt manchmal zu Verwirrung. und mit void (x) fügen wir einen Overhead bei der Verarbeitung hinzu.

Wenn Sie kein Eingabeargument verwenden, verwenden Sie

void foo(int __attribute__((unused))key)
{
}

Wenn Sie die in der Funktion definierte Variable nicht verwenden

void foo(int key)
{
   int hash = 0;
   int bkt __attribute__((unused)) = 0;

   api_call(x, hash, bkt);
}

Verwenden Sie später die Hash-Variable für Ihre Logik, benötigen Sie jedoch kein bkt. Definieren Sie bkt als nicht verwendet, andernfalls sagt der Compiler "bkt set bt not used".

HINWEIS: Dies dient nur dazu, die Warnung zu unterdrücken, die nicht zur Optimierung dient.


1
Sie fügen bei der Verarbeitung keinen Overhead hinzu void(x), der Compiler optimiert ihn.
Majora320

4

Ich habe das gleiche Problem. Ich habe eine Bibliothek des dritten Teils benutzt. Wenn ich diese Bibliothek kompiliere, beschwert sich der Compiler (gcc / clang) über nicht verwendete Variablen.

So was

test.cpp: 29: 11: Warnung: Variable 'magic' gesetzt, aber nicht verwendet [-Wunused-but-set-variable] short magic [] = {

test.cpp: 84: 17: Warnung: nicht verwendete Variable 'before_write' [-Wunused-variable] int64_t before_write = Thread :: currentTimeMillis ();

Die Lösung ist also ziemlich klar. Wenn Sie -Wno-unusedals gcc / clang CFLAG hinzufügen, werden alle "nicht verwendeten" Warnungen unterdrückt, auch wenn Sie sie -Wallfestgelegt haben.

Auf diese Weise MÜSSEN Sie keinen Code ändern.


1
Dies ist in Ordnung, wenn Sie tatsächlich alle nicht verwendeten Warnungen ignorieren möchten, dies ist jedoch fast nie der Fall. Es sind normalerweise nur bestimmte Instanzen, die Sie ignorieren möchten.
Dan Bechard

1

In MSVC reicht es aus, die zu kompilierende Nummer als / wd # anzugeben, um eine bestimmte Warnung zu unterdrücken. Meine CMakeLists.txt enthält den folgenden Block:

If (MSVC)
    Set (CMAKE_EXE_LINKER_FLAGS "$ {CMAKE_EXE_LINKER_FLAGS} / NODEFAULTLIB: LIBCMT")
    Add_definitions (/W4 /wd4512 /wd4702 /wd4100 /wd4510 /wd4355 /wd4127)
    Add_definitions (/D_CRT_SECURE_NO_WARNINGS)
Elseif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC)
    Add_definitions (-Wall -W -pedantic)
Else ()
    Message ("Unknown compiler")
Endif ()

Jetzt kann ich nicht genau sagen, was / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127 bedeutet, da ich MSVC drei Jahre lang keine Aufmerksamkeit schenke, aber sie unterdrücken superpedantische Warnungen, die das Ergebnis nicht beeinflussen.


0

Ich habe gesehen, wie dieser Stil verwendet wurde:

if (when || who || format || data || len);

14
Hm. Ich kann nicht sagen, dass mir das gefällt, da dies voraussetzt, dass alle beteiligten Parameter in einen Bool konvertiert werden können.
Suma

1
Dies ist keine wirklich gute Konvention, obwohl der Compiler sie mit ziemlicher Sicherheit optimieren wird, es ist nicht wirklich klar, was los ist und könnte statische Quellenprüfer verwirren. Verwenden Sie hier meiner Meinung nach besser einen der anderen Vorschläge.
ideasman42

1
Ich kann nicht glauben, dass ich immer noch Antworten darauf bekomme. Die Frage besagte, dass es sich um C handelte. Ja, in einer anderen Sprache würde dies nicht funktionieren.
Iustin

2
Ich würde es nicht verwenden, aber +1 für den Neuheitsfaktor.
Mgalgs

2
Das Überprüfen der Wahrheit von Variablen kann Warnungen für Strukturen geben. z.B. struct { int a; } b = {1}; if (b);GCC warnt , used struct type value where scalar is required.
ideasman42

-1

Für die Aufzeichnung mag ich Hiobs Antwort oben, aber ich bin neugierig auf eine Lösung, bei der nur der Variablenname allein in einer "Nichtstun" -Anweisung verwendet wird:

void foo(int x) {
    x; /* unused */
    ...
}

Sicher, das hat Nachteile; Ohne die "unbenutzte" Notiz sieht es beispielsweise eher nach einem Fehler als nach einer absichtlichen Codezeile aus.

Der Vorteil ist, dass keine DEFINE benötigt wird und die Warnung entfernt wird.

Gibt es Leistungs-, Optimierungs- oder andere Unterschiede?


2
Ich habe dies entweder mit MSVC verwendet, aber GCC gibt die Warnung "Anweisung ohne Wirkung" aus. Hiobs Lösung ist also der richtige Weg.
Dmitrii Semikin

Dieser Ansatz generiert immer noch eine Warnung in XCode
MOK9
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.