pointer c++ casting compiler-warnings void suppress-warnings

c++ - c void pointer function



¿Qué hace realmente el casting a `void`? (4)

Casting to anid se usa para suprimir las advertencias del compilador. La Standard dice en §5.2.9 / 4 dice:

Cualquier expresión se puede convertir explícitamente al tipo "cv void". El valor de la expresión se descarta.

Una declaración de uso frecuente como (void)x; permite suprimir advertencias sobre la variable no utilizada x . Pero si intento compilar lo siguiente, obtengo algunos resultados que no entiendo:

int main() { int x; (short)x; (void)x; (int)x; }

Compilando esto con g ++, recibo las siguientes advertencias:

$ g++ test.cpp -Wall -Wextra -o test test.cpp: In function ‘int main()’: test.cpp:4:13: warning: statement has no effect [-Wunused-value] (short)x; ^ test.cpp:6:11: warning: statement has no effect [-Wunused-value] (int)x; ^

Así que concluyo que lanzar al void es muy diferente de lanzar a cualquier otro tipo, sea el tipo de destino lo mismo que decltype(x) o algo diferente. Mi suposición sobre posibles explicaciones es:

  • Es solo una convención que (void)x; pero no los otros lanzamientos suprimirán las advertencias. Todas las declaraciones por igual no tienen ningún efecto.
  • Esta diferencia está relacionada de alguna manera con el hecho de que void x; no es una declaración válida mientras sea short x; es.

¿Cuál de estos, si alguno, es más correcto? Si no hay ninguno, ¿cómo se puede explicar la diferencia en las advertencias del compilador?


El estándar no obliga a generar una advertencia ("diagnóstico" en estándar) para variables locales no utilizadas o parámetros de función. Del mismo modo, no ordena cómo se podría suprimir dicha advertencia. Lanzar una expresión variable al void para suprimir esta advertencia se ha convertido en una expresión idiomática en la comunidad C y posterior C ++ porque el resultado no se puede usar de ninguna manera (que no sea, por ejemplo, (int)x ), por lo que es poco probable que el código correspondiente sea solo desaparecido. P.ej:

(int)x; // maybe you meant f((int)x); (void)x; // cannot have intended f((void)x); (void)x; // but remote possibility: f((void*)x);

Personalmente, considero que esta convención aún es muy oscura, por eso prefiero usar una plantilla de función:

template<typename T> inline void ignore(const T&) {} // e.g. ignore(x);

Sin embargo, la forma idiomática de ignorar los parámetros de la función es omitir su nombre (como se ve arriba). Un uso frecuente que tengo para esta función es cuando necesito poder nombrar un parámetro de función en código compilado condicionalmente, como una assert . Me parece, por ejemplo, lo siguiente más legible que el uso de #ifdef NDEBUG :

void rate(bool fantastic) { assert(fantastic); ignore(fantastic); }


Esta declaración:

(void)x;

Dice "Ignorar el valor de x". No existe un tipo de void : es la ausencia de un tipo. Entonces es muy diferente de esto:

(int)x;

Que dice "Tratar x como si fuera un número entero". Cuando se ignora el entero resultante, aparece una advertencia (si está habilitado).

Cuando ignora algo que no es nada, GCC no lo considera un problema, y ​​con razón, dado que anular es una forma idiomática de ignorar una variable explícitamente en C y C ++.


Posible uso:

auto it = list_.before_begin(); for (auto& entry : list_) { (void)entry; //suppress warning ++it; }

Ahora el iterador ''it'' apunta al último elemento