wake-up-neo.com

Wie kann ich eine Warnung über nicht verwendete Variablen am besten stummschalten?

Ich habe eine plattformübergreifende Anwendung, und in einigen Funktionen werden nicht alle an Funktionen übergebenen Werte verwendet. Daher bekomme ich von GCC eine Warnung, dass nicht verwendete Variablen vorhanden sind.

Was wäre der beste Weg, um die Warnung zu codieren?

Ein #ifdef rund um die Funktion? 

#ifdef _MSC_VER
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight)
#else
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal /*qrLeft*/, qreal /*qrTop*/, qreal /*qrWidth*/, qreal /*qrHeight*/)
#endif
{

Das ist so hässlich, scheint aber so zu sein, wie es der Compiler vorziehen würde.

Oder ordne ich der Variablen am Ende der Funktion Null zu? (was ich hasse, weil er etwas im Programmablauf ändert, um eine Compiler-Warnung auszuschalten).

Gibt es einen richtigen Weg?

185
Phil Hannent

Sie können setzen Sie es in "(void)var;" Ausdruck (macht nichts), damit ein Compiler sieht, dass es verwendet wird Dies ist zwischen Compilern portierbar.

Z.B.

void foo(int param1, int param2)
{
    (void)param2;
    bar(param1);
}

Oder,

#define UNUSED(expr) do { (void)(expr); } while (0)
...

void foo(int param1, int param2)
{
    UNUSED(param2);
    bar(param1);
}
270
Alex B

In GCC und Clang können Sie die Präprozessor-Direktive __attribute__((unused)) verwenden, um Ihr Ziel zu erreichen.
Zum Beispiel:

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

Ihre aktuelle Lösung ist am besten - kommentieren Sie den Parameternamen aus, wenn Sie ihn nicht verwenden. Dies gilt für alle Compiler, so dass Sie den Vorprozessor nicht speziell für GCC verwenden müssen.

34
alex tingle

C++ 17 stellt jetzt das [[maybe_unused]]-Attribut bereit.

http://en.cppreference.com/w/cpp/language/attributes

Ganz nett und standard.

29
scx

Ein Kollege hat mich gerade auf dieses nette kleine Makro hingewiesen hier

Zur Vereinfachung füge ich das Makro unten hinzu.

#ifdef UNUSED
#Elif defined(__GNUC__) 
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 
#Elif defined(__LCLINT__) 
# define UNUSED(x) /*@[email protected]*/ x 
#else 
# define UNUSED(x) x 
#endif

void dcc_mon_siginfo_handler(int UNUSED(whatsig))
23
user194119

gcc kennzeichnet diese Warnungen nicht standardmäßig. Diese Warnung muss entweder explizit durch Übergabe von -Wunused-parameter an den Compiler oder implizit durch Übergabe von -Wall -Wextra (oder möglicherweise einer anderen Kombination von Flags) aktiviert worden sein.

Nicht verwendete Parameterwarnungen können einfach unterdrückt werden, indem Sie -Wno-unused-parameter an den Compiler übergeben. Beachten Sie jedoch, dass dieses Deaktivierungsflag nach möglichen Aktivierungsflags für diese Warnung in der Compiler-Befehlszeile stehen muss, damit es wirksam werden kann.

22
Digital Trauma

Noch sauberer ist das Auskommentieren von Variablennamen:

int main(int /* argc */, char const** /* argv */) {
  return 0;
}
21

C++ 17-Update

In C++ 17 erhalten wir das Attribut [[maybe_unused]], das in [dcl.attr.unused] behandelt wird.

Das Attribut-Token maybe_unused zeigt an, dass ein Name oder eine Entität möglicherweise absichtlich nicht verwendet wird. Es sollte höchstens einmal in jeder Attributliste und keine Attribut-Argument-Klausel darf vorhanden sein . ...

Beispiel:

 [[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2) {
  [[maybe_unused]] bool b = thing1 && thing2;
    assert(b);
 }

Implementierungen sollten nicht warnen, dass b nicht verwendet wird, ob NDEBUG definiert ist oder nicht. - Ende Beispiel]

Für das folgende Beispiel:

int foo ( int bar) {
    bool unused_bool ;
    return 0;
}

Sowohl clang als auch gcc erstellen eine Diagnose mit -Wall -Wextra für bar und unused_bool ( Live ).

Beim Hinzufügen von [[maybe_unused]] wird die Diagnose stummgeschaltet:

int foo ([[maybe_unused]] int bar) {
    [[maybe_unused]] bool unused_bool ;
    return 0;
}

sehe es live .

Vor C++ 17

In C++ 11 könnte eine alternative Form des UNUSED-Makros mit einem Lambda-Ausdruck (via Ben Deane) mit einem Capture der nicht verwendeten Variablen gebildet werden:

#define UNUSED(x) [&x]{}()

Der sofortige Aufruf des Lambda-Ausdrucks sollte im folgenden Beispiel optimiert werden:

int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}

wir können in godbolt sehen, dass der Anruf weg optimiert ist:

foo(int):
xorl    %eax, %eax
ret
16
Shafik Yaghmour

makrolose und portable Möglichkeit, einen oder mehrere Parameter als nicht verwendet zu erklären:

template <typename... Args> inline void unused(Args&&...) {}

int main(int argc, char* argv[])
{
    unused(argc, argv);
    return 0;
}
11
Philippe

Die Verwendung von Präprozessoranweisungen wird meistens als schlecht angesehen. Idealerweise möchten Sie sie wie die Pest vermeiden. Denken Sie daran, dass der Compiler den Code leicht verständlich macht, sodass andere Programmierer den Code viel schwieriger verstehen können. Ein paar Dutzend solcher Fälle machen es hier und da sehr schwer, später selbst oder für andere zu lesen.

Eine Möglichkeit wäre, Ihre Parameter in eine Art Argumentklasse zusammenzufassen. Sie können dann nur eine Teilmenge der Variablen verwenden (entspricht der Zuweisung von 0) oder unterschiedliche Spezialisierungen dieser Argumentklasse für jede Plattform. Dies kann sich jedoch nicht lohnen, Sie müssen analysieren, ob es passt.

Wenn Sie unmögliche Vorlagen lesen können, finden Sie möglicherweise erweiterte Tipps im Buch "Exceptional C++". Wenn die Leute, die Ihren Code lesen würden, ihre Fähigkeiten bekommen könnten, um die verrückten Dinge, die in diesem Buch gelehrt werden, zu erfassen, dann hätten Sie einen schönen Code, der auch leicht zu lesen ist. Der Compiler weiß auch, was Sie tun (anstatt alles durch Vorverarbeitung zu verbergen)

7
Ben Dadsetan

Zunächst wird die Warnung durch die Variablendefinition in der Quelldatei und nicht in der Headerdatei generiert. Der Header kann makellos bleiben und sollte auch verwendet werden, da Sie zum Erstellen der API-Dokumentation möglicherweise etwas wie doxygen verwenden. 

Ich gehe davon aus, dass Sie eine völlig andere Implementierung in Quelldateien haben. In diesen Fällen können Sie den fehlerhaften Parameter entweder auskommentieren oder einfach nur den Parameter schreiben. 

Beispiel:

func(int a, int b)
{
    b;
    foo(a);
}

Dies mag kryptisch erscheinen, so dass ein Makro wie UNUSED definiert wurde. So hat MFC es gemacht:

#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif

Auf diese Weise sehen Sie die Warnung immer noch in Debug-Builds. Dies könnte hilfreich sein.

6
rioki

Ist es nicht sicher, Parameternamen immer auszukommentieren? Wenn nicht, können Sie so etwas tun

#ifdef _MSC_VER
# define P_(n) n
#else
# define P_(n)
#endif

void ProcessOps::sendToExternalApp(
    QString sAppName, QString sImagePath,
    qreal P_(qrLeft), qreal P_(qrTop), qreal P_(qrWidth), qreal P_(qrHeight))

Es ist etwas weniger hässlich.

Mit __unused können Sie dem Compiler mitteilen, dass die Variable möglicherweise nicht verwendet wird.

- (void)myMethod:(__unused NSObject *)theObject    
{
    // there will be no warning about `theObject`, because you wrote `__unused`

    __unused int theInt = 0;
    // there will be no warning, but you are still able to use `theInt` in the future
}
2
OlDor

Verwenden Sie die Flagge des Compilers, z. Flag für GCC: -Wno-unused-variable

2
user6468372

Die Verwendung einer UNREFERENCED_PARAMETER(p) könnte funktionieren. Ich weiß, dass es in WinNT.h für Windows-Systeme definiert ist und auch leicht für gcc definiert werden kann (falls es nicht bereits vorhanden ist).

UNREFERENCED PARAMETER(p) ist definiert als

#define UNREFERENCED_PARAMETER(P)          (P)

in WinNT.h.

2
Joshua

In C++ 11 verwende ich diese Lösung:

template<typename... Ts> inline void Unreferenced(Ts&&...) {}

int Foo(int bar) 
{
    Unreferenced(bar);
    return 0;
}

int Foo2(int bar1, int bar2) 
{
    Unreferenced(bar1, bar2);
    return 0;
}

Verifiziert, dass es portabel ist (zumindest bei modernen msvc, clang und gcc) und keinen zusätzlichen Code erzeugt, wenn Optimierungen aktiviert sind. Ohne Optimierung wird der zusätzliche Funktionsaufruf ausgeführt und Verweise auf die Parameter werden in den Stack kopiert es sind keine Makros beteiligt.

Wenn der zusätzliche Code ein Problem ist, können Sie stattdessen diese Deklaration verwenden:

(decltype(Unreferenced(bar1, bar2)))0;

an diesem Punkt bietet ein Makro jedoch eine bessere Lesbarkeit:

#define UNREFERENCED(...) { (decltype(Unreferenced(__VA_ARGS__)))0; }
1
Nampo

Das funktioniert gut, erfordert aber C++ 11

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}
1

Ich habe festgestellt, dass die meisten Antworten nur für lokale, nicht verwendete Variablen funktionieren, und es wird ein Kompilierungsfehler für nicht verwendete statische globale Variablen verursacht. 

Ein weiteres Makro musste die Warnung vor nicht verwendeten statischen globalen Variablen unterdrücken.

template <typename T>
const T* UNUSED_VARIABLE(const T& dummy) { 
    return &dummy;
}
#define UNUSED_GLOBAL_VARIABLE(x) namespace {\
    const auto dummy = UNUSED_VARIABLE(x);\
}

static int a = 0;
UNUSED_GLOBAL_VARIABLE(a);

int main ()
{
    int b = 3;
    UNUSED_VARIABLE(b);
    return 0;
}

Dies funktioniert, weil für anonyme statische globale Variablen im anonymen Namespace keine Warnung gemeldet wird. 

C++ 11 ist jedoch erforderlich

 g++  -Wall -O3  -std=c++11 test.cpp
0
FaceBro