Po co rzutować nieużywaną wartość parametru funkcji na void?

98

W jakimś projekcie C widziałem ten kod:

static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
    (void)ud;
    (void)osize;
    /* some code not using `ud` or `osize` */
    return ptr;
}

Czy te dwa rzuty, które mają zostać unieważnione, służą jakimkolwiek celom?

bastibe
źródło
Głosowanie za zamknięciem, ponieważ prawidłowa odpowiedź (blokowanie ostrzeżeń kompilatora o nieużywanych parametrach) znajduje się w połączonym pytaniu Charlesa.
TED,
@Cody Gray - Z tego powodu zostało zamknięte. Jednak w rzeczywistości nie była to dupa tego pytania. 689677 mówił o rzutowaniu powrotów do void, a nie parametrów.
TED,
19
Właściwie oba duplikaty nie odpowiadają temu pytaniu. Jeden to C ++, drugi dotyczy zwracanych wartości. To nie są te same rzeczy . Czy są jakieś duplikaty parametru C?
Matt Joiner,
2
To jest inne pytanie niż to, co obejmowały sugerowane duplikaty. Widzę jednak, dlaczego popełniono błąd. Ponownie otwarty (oczywiście).
Tim Post
4
Uwaga: proszę nie zamykać tego jako duplikatu pytania w C ++, ponieważ C ++ używa go (void)do nieco innego efektu. To pytanie dotyczy C
Antti Haapala

Odpowiedzi:

89

Ma to na celu uniknięcie ostrzeżeń ze strony kompilatora, ponieważ niektóre parametry są nieużywane.

Benoit Thiery
źródło
3
Jaki jest najlepszy sposób na
pominięcie
@Benoit, co właściwie robi casting to void? Czy jego jedyną funkcją jest pokazanie kompilatorowi, że celowo coś ignorujesz lub faktycznie coś robisz (void), a kiedy kompilator to zobaczy, po prostu policzy to jako coś, co zrobił ze zmienną i dlatego nie wyświetli ostrzeżenia?
Tan Wang
2
@TanWang Jego jedyną funkcją jest pokazanie kompilatorowi, że celowo coś ignorujesz. To nic nie da w czasie wykonywania.
zwol
14

Powodem posiadania nieużywanych parametrów w prototypie jest zwykle to, że funkcja musi być zgodna z jakimś zewnętrznym API - być może jest to funkcja biblioteczna lub wskaźnik do tej funkcji jest przekazywany do innej funkcji, która oczekuje takiej konwencji wywoływania. Jednak nie wszystkie argumenty używane przez konwencję wywoływania są w rzeczywistości potrzebne w samej funkcji.

Powodem podania nazwy parametru w treści jest uniknięcie ostrzeżeń, takich jak

unused.c: In function l_alloc’:
unused.c:3:22: warning: unused parameter ud [-Wunused-parameter]
 void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
                      ^~

To ostrzeżenie można wyeliminować, używając rzeczywistego parametru w treści funkcji. Na przykład, jeśli masz następujące oświadczenie:

ud;

To ostrzeżenie jest teraz zniesione. Jednak teraz GCC wyświetli kolejne ostrzeżenie:

unused.c:5:5: warning: statement with no effect [-Wunused-value]
     ud;
     ^~

To ostrzeżenie mówi, że instrukcja ud;, chociaż jest poprawna składniowo w C, w ogóle nie wpływa na nic i prawdopodobnie jest błędem, podobnie jak instrukcja

abort;

które być może powinno być napisane jako abort();zamiast tego, żeby coś zrobiło.

I w tym miejscu (void)pojawia się rzutowanie - powie kompilatorowi jednoznacznie i wyraźnie, że instrukcja ma absolutnie nie mieć żadnego efektu.

Antti Haapala
źródło