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.