¿Cómo puedo corregir advertencias como: “comparación entre firmado y sin firmar”?

6 minutos de lectura

avatar de usuario
Jorge

Me han aconsejado usar las siguientes opciones con GCC, ya que ayuda a evitar muchos errores comunes. Activa un montón de advertencias y -Werror los convierte en errores.

gcc -pedantic -W -Wall -Wextra -Wshadow -Wstrict-overflow=5 -Wwrite-strings -std=c99 -Werror

Dado el siguiente código de prueba:

#include <stdio.h>

int main(void)
{
    int arr[8]={0,10,20,30,40,50,60,70};
    int x;

    printf("sizeof(arr): %d\n", sizeof(arr));
    printf("sizeof(int): %d\n", sizeof(int));

    for(x = 0; x < sizeof(arr)/sizeof(int); x++)
    {
        printf("%d\n",arr[x]);
    }

    return 0;
}

Entiendo esto:

test.c:11: error: comparison between signed and unsigned

Sé que una forma de solucionar esto es desactivar las advertencias, pero al final no me han hecho usar esta configuración para desactivarlas.

Otra forma es lanzar las cosas, pero me han dicho que la conversión está obsoleta.

Además, podría convertir x en un unsigned int:

unsigned x;

Pero no resuelve el problema general cuando tengo que comparar valores firmados con valores sin firmar usando estas opciones del compilador. ¿Hay una forma más limpia en lugar de lanzar?

  • Tenga en cuenta que sizeof devuelve un size_t que debe imprimirse utilizando %zu

    – phuclv

    24 de marzo de 2017 a las 13:34

Reemplazar

int x;
/* ... */
for(x=0;x<sizeof(arr) / sizeof(int);x++)

por

for(size_t x=0;x<sizeof(arr) / sizeof(int);x++)

Pero no resuelve el problema general cuando tengo que comparar valores firmados con valores sin firmar usando estas opciones del compilador. ¿Hay una forma más limpia en lugar de lanzar?

En tales casos, intente averiguar si el número firmado puede tener un valor que provoque un desbordamiento. Si no, puede ignorar la advertencia. De lo contrario, una conversión al tipo sin firmar (si es del mismo tamaño o más grande que el componente firmado) es suficiente.

  • Estoy de acuerdo con esta respuesta. También tenga en cuenta que la transmisión no está en desuso, pero probablemente no se recomienda para un principiante porque puede llevarlo a algunos malos hábitos.

    – Borbus

    13 mayo 2009 a las 19:39

  • Esta es la mejor respuesta, pero estoy introduciendo un concepto de C++ en una pregunta sobre C. No he usado C estricto por un tiempo, pero no creo que puedas declarar tu variable de índice dentro del ciclo como lo haces en C++ .

    – Adrián McCarthy

    14 mayo 2009 a las 20:21

  • @Adrian McCarthy: Ver C99, 6.8.5.3.1: […] “Si la cláusula-1 es una declaración, el alcance de los identificadores que declara es el resto de la declaración y el bucle completo, incluidas las otras dos expresiones; se alcanza en el orden de ejecución antes de la primera evaluación de la expresión de control. “

    – dirkgently

    17 mayo 2009 a las 20:58

  • Declarar la variable allí es C99 y no es compatible con compiladores más antiguos. Si le importa, obviamente podría cambiar igualmente la declaración y mantenerla en la parte superior de la función.

    – piscina

    22 de agosto de 2011 a las 4:33

Esto realmente depende del tipo de datos. Es posible evitar esto mediante la conversión implícita de los valores a un tipo que contenga un superconjunto de todos los valores disponibles en el tipo con y sin signo. Por ejemplo, podría usar un valor con signo de 64 bits para comparar un valor de 32 bits sin signo y un valor de 32 bits con signo.

Sin embargo, este es un caso de esquina y debe realizar operaciones como verificar el tamaño de sus tipos. Su mejor solución es usar el mismo tipo para ambos operandos.

Si debe emitir, considere que podría estar causando un desbordamiento y considere si eso es importante para su aplicación o no.

avatar de usuario
dmckee — gatito ex-moderador

El quid de la cuestión es que comparar valores con y sin signo admite algunos casos extraños. Considere, por ejemplo, que lo que sucede en la longitud de la matriz sin signo es mayor que el máximo que puede representar un int con signo. El contador firmado se desborda (quedando “menos que” el tamaño de la matriz), y comienza a direccionar la memoria que no pretendía…

El compilador genera una advertencia para asegurarse de que está pensando en ellos. Utilizando -Werror promueve esa advertencia a un error y detiene la compilación.

Sea riguroso al elegir la firma de sus tipos, o deseche el problema cuando esté seguro de que no se aplica, o deshágase de -Werror y haga una política para abordar todas las advertencias con una corrección o una explicación…

Una solución alternativa sería deshabilitar selectivamente esa advertencia en este caso especial. CCG se ha ignorado el diagnóstico de pragma “-Wsomething”

// Disable a warning for a block of code:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
// ... Some code where the specified warning should be suppressed ...
#pragma GCC diagnostic pop

Las versiones recientes de GCC (no estoy seguro desde cuándo, pero 4.8.x debería admitirlo) muestran la opción -Wsomething correspondiente. Esto es importante ya que la mayoría de las opciones de advertencia no se configuran explícitamente sino en bloque con opciones como -Wall. Un mensaje de error se vería así:

readers.c: In function ‘buffered_fullread’:
readers.c:864:11: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
    if(got < sizeof(readbuf)) /* That naturally catches got == 0, too. */

los [-Werror=sign-compare] parte le dice Puede usar “Wsign-compare” para “Wsomething” para suprimir la advertencia.

Y, por supuesto, solo debe hacerlo cuando sea apropiado (no ayuda mucho a la legibilidad), por ejemplo, cuando se desea exactamente el comportamiento sobre el que advierte el compilador (o, si no puede introducir cambios más grandes en el código base).

una opción sería la bandera adicional “-Wno-sign-compare” 🙂

  • Ocultar esta advertencia puede ocultar errores legítimos.

    – Nick Desaulniers

    4 de marzo de 2018 a las 10:57

  • por eso la carita sonriente!

    – Frankster

    5 de marzo de 2018 a las 17:48

  • Un emoticón es prácticamente la peor manera posible de señalar algo tan importante, especialmente porque las personas que están aprendiendo a programar encuentran estas respuestas. En lugar de ser tímido, intente hacer una adición útil a su respuesta para explicar por qué esta es una solución que técnicamente funcionaría aunque no debería usarse.

    – Antonio

    19 de julio de 2018 a las 15:28


test.c:11: error: comparison between signed and unsigned

Podría declarar x como un int sin signo, ya que size_t no está firmado

EDITAR:

Si no quieres emitir y no quieres declararlo como sin firmar, no creo que haya mucho que hacer.

Tal vez las operaciones bit a bit sean una forma de resolverlo, eliminando el bit de signo. Debo decir que, en mi opinión, es muy cuestionable.

  • Ocultar esta advertencia puede ocultar errores legítimos.

    – Nick Desaulniers

    4 de marzo de 2018 a las 10:57

  • por eso la carita sonriente!

    – Frankster

    5 de marzo de 2018 a las 17:48

  • Un emoticón es prácticamente la peor manera posible de señalar algo tan importante, especialmente porque las personas que están aprendiendo a programar encuentran estas respuestas. En lugar de ser tímido, intente hacer una adición útil a su respuesta para explicar por qué esta es una solución que técnicamente funcionaría aunque no debería usarse.

    – Antonio

    19 de julio de 2018 a las 15:28


avatar de usuario
david thornley

Suprimimos esta advertencia en nuestras compilaciones de Visual Studio, ya que sucede mucho y casi nunca significa algo significativo. Por supuesto, no todos los estándares de codificación lo permiten.

Puede hacer que los tipos coincidan (por ejemplo, declarando que las variables sean size_t o unsigned int en lugar de int), o puede convertir, o puede cambiar su línea de compilación. Eso es todo.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad