Jak ukryć ostrzeżenia „nieużywany parametr” w C?


210

Na przykład:

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

W C ++ byłem w stanie /*...*/skomentować parametry. Ale oczywiście nie w C, gdzie daje mi to błąd error: parameter name omitted.



4
@CiroSantilli To pytanie ma więcej głosów pozytywnych, lepiej byłoby oznaczyć drugie pytanie jako duplikat.
— sashoalm


-Wno-unused-parameter, jest po prostu zbyt głośno i rzadko łapie błędy, szczególnie. kiedy -Wshadowjest używany.
— Trass3r

Odpowiedzi:


297

Zwykle piszę takie makro:

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

Możesz użyć tego makra do wszystkich nieużywanych parametrów. (Uwaga: działa to na dowolnym kompilatorze).

Na przykład:

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

45
Po prostu używam (void) x bezpośrednio
— Prof. Falken

6
chociaż jest to jedyny przenośny sposób AFAIK, irytacja może być myląca, jeśli użyjesz zmiennej później i zapomnisz o usunięciu nieużywanej linii. dlatego nieużywane GCC jest miłe.
— ideasman42

6
@CookSchelling: Ach, ale nie powinieneś tego tak używać. Zrobić coś takiego: void f(int x) {UNUSED(x);}.
— Job

9
@Alcott, ponieważ (jak w moim przypadku) funkcja może być jedną z wielu, które muszą mieć tę samą sygnaturę, ponieważ są do niej wskazywane wskaźniki funkcji.
— josch

17
Używam, #define UNUSED(...) (void)(__VA_ARGS__)co pozwala mi zastosować to do wielu zmiennych.
— Matthew Mitchell,

110

W gcc możesz opisać parametr za pomocą unusedatrybutu .

Ten atrybut dołączony do zmiennej oznacza, że ​​zmienna ma być prawdopodobnie nieużywana. GCC nie wyświetli ostrzeżenia dla tej zmiennej.

W praktyce osiąga się to poprzez umieszczenie __attribute__ ((unused))tuż przed parametrem. Na przykład:

void foo(workerid_t workerId) { }

staje się

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

24
Dla każdego początkującego, takiego jak ja, oznacza to postawienie się __attribute__ ((unused))przed argumentem.
— josch

2
@ josch Myślę, że masz całkowitą rację, ale dokumentacja wydaje się sugerować, że należy ją umieścić po parametrze. Obie opcje są prawdopodobnie obsługiwane bez problemów.
— Antonio

Pamiętaj również, że __attribute__((unused))jest to zastrzeżone rozszerzenie GCC . Jest obsługiwany przez inne kompilatory, ale zakładam, że to nie będzie działać z MSVC. Nie jest to jednak bezpośrednio część standardu kompilatora, więc nie jest tak przenośne, jak niektóre inne opcje
— Zoe

58

Możesz użyć nieużywanego atrybutu gcc / clang, jednak ja używam tych makr w nagłówku, aby uniknąć posiadania specyficznych atrybutów gcc w całym źródle, również posiadanie __attribute__wszędzie jest trochę gadatliwe / brzydkie.

#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

Następnie możesz zrobić ...

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

Wolę to, ponieważ pojawia się błąd, jeśli spróbujesz użyć barkodu w dowolnym miejscu, więc nie możesz przez pomyłkę pozostawić atrybutu.

i dla funkcji ...

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

Uwaga 1):
O ile mi wiadomo, MSVC nie ma odpowiednika __attribute__((__unused__)).

Uwaga 2): makro nie będzie działać na argumentach, które zawierają nawias, więc jeśli masz argument jak ty nie może zrobić, albo , to jedynym minusem do makro znalazłem do tej pory, w tych przypadkach spadnę z powrotem do
UNUSED
float (*coords)[3]
float UNUSED((*coords)[3])float (*UNUSED(coords))[3]UNUSED(void)coords;


A może tylko #define __attribute__(x)dla środowiska innego niż GCC (AFAIK żaden z nich nie __attribute__jest obsługiwany przez MSVC)?
— Franklin Yu,

To może działać, ale prefiksy dunder są zarezerwowane dla kompilatora, więc wolałbym tego uniknąć.
— ideasman42,

Dla mojego gcc przynajmniej umieszczenie specyfikatora atrybutu przed identyfikatorem wydaje się działać poprawnie dla funcs, vars i parametru, więc coś takiego jak # zdefiniować POSSIBLY_UNUSED (identyfikator) atrybut __ ((__ nieużywany )) identyfikator może być użyte dla wszystkich trzech
— Britton Kerin

Kiedy go umieszczam, dostaję warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
— ideasman42

19

Z gcc z nieużywanym atrybutem:

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

16

Widząc, że jest to oznaczone jako gcc, możesz użyć przełącznika wiersza poleceń Wno-unused-parameter.

Na przykład:

gcc -Wno-unused-parameter test.c

Oczywiście wpływa to na cały plik (i może projekt, w zależności od ustawienia przełącznika), ale nie musisz zmieniać żadnego kodu.


7

Specyficznym sposobem gcc / g ++ na wyłączenie ostrzeżenia o nieużywanym parametrze dla bloku kodu źródłowego jest dołączenie go z następującymi instrukcjami pragma:

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

Clang obsługuje te pragmatyczne diagnozy, a także clang.llvm.org/docs/…
— eush77 28.04.17

4

Oznaczenie atrybutu jest idealnym sposobem. MAKRO prowadzi do zamieszania. i używając void (x), dodajemy koszty ogólne w przetwarzaniu.

Jeśli nie używasz argumentu wejściowego, użyj

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

Jeśli nie używasz zmiennej zdefiniowanej w funkcji

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

   api_call(x, hash, bkt);
}

Teraz później używasz zmiennej hash dla twojej logiki, ale nie potrzebuje bkt. zdefiniuj bkt jako nieużywany, w przeciwnym razie kompilator powie „bkt set bt not used”.

UWAGA: Ma to na celu wyłączenie ostrzeżenia, a nie optymalizację.


1
Nie dodajesz żadnego narzutu podczas przetwarzania void(x), kompilator zoptymalizuje go.
— Majora320

4

Mam ten sam problem. Użyłem biblioteki trzeciej części. Kiedy skompiluję tę bibliotekę, kompilator (gcc / clang) będzie narzekał na nieużywane zmienne.

Lubię to

test.cpp: 29: 11: ostrzeżenie: zmienna „magia” ustawiona, ale nieużywana [-Zużyta-ale-ustawiona-zmienna] krótka magia [] = {

test.cpp: 84: 17: ostrzeżenie: nieużywana zmienna 'before_write' [-Wunused-zmienna] int64_t before_write = Wątek :: currentTimeMillis ();

Więc rozwiązanie jest całkiem jasne. Dodanie -Wno-unusedjako CFCAG gcc / clang spowoduje usunięcie wszystkich „nieużywanych” ostrzeżeń, nawet jeśli są -Wallustawione.

W ten sposób NIE POTRZEBUJESZ zmiany kodu.


1
Jest to w porządku, jeśli faktycznie chcesz zignorować wszystkie nieużywane ostrzeżenia, ale prawie nigdy tak nie jest. Zwykle są to określone przypadki, które chcesz zignorować.
— Dan Bechard,

1

W MSVC, aby pominąć określone ostrzeżenie, wystarczy podać jego numer do kompilatora jako / wd #. Mój CMakeLists.txt zawiera taki blok:

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 ()

Teraz nie mogę powiedzieć, co dokładnie oznaczają / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127, ponieważ nie zwracam uwagi na MSVC przez trzy lata, ale tłumią one superantyczne ostrzeżenia, które nie wpływają na wynik.


0

Widziałem używany ten styl:

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

14
Hm Nie mogę powiedzieć, że mi się podoba, ponieważ zakłada to, że wszystkie zaangażowane parametry można przekształcić w bool.
— Suma,

1
Nie jest to naprawdę dobra konwencja, mimo że kompilator prawie na pewno ją zoptymalizuje, nie jest do końca jasne, co się dzieje i może mylić statyczne sprawdzanie źródeł. lepiej skorzystaj z jednej z innych sugestii tutaj IMHO.
— ideasman42

1
Nie mogę uwierzyć, że wciąż otrzymuję odpowiedzi na to. Pytanie brzmiało: C. Tak, w innym języku to nie zadziała.
— Iustin

2
Nie użyłbym tego, ale +1 dla czynnika nowości.
— mgalgs,

2
sprawdzanie prawdziwości zmiennych może dawać ostrzeżenia dla struktur. na przykład. struct { int a; } b = {1}; if (b);GCC ostrzega used struct type value where scalar is required.
— ideasman42

-1

Dla przypomnienia, podoba mi się powyższa odpowiedź Hioba, ale jestem ciekawa rozwiązania, w którym sama nazwa zmiennej byłaby użyta w instrukcji „nic nie robić”:

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

Jasne, ma to wady; na przykład bez „nieużywanej” nuty wygląda raczej na pomyłkę niż zamierzoną linię kodu.

Korzyścią jest to, że DEFINE nie jest potrzebne i pozbywa się ostrzeżenia.

Czy jest jakaś wydajność, optymalizacja lub inne różnice?


2
Użyłem tego z MSVC, ale GCC podnosi ostrzeżenie „oświadczenie bez efektu”. Tak więc rozwiązaniem jest Job.
— Dmitrii Semikin

Takie podejście nadal generuje ostrzeżenie w XCode
— MOK9
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.