2009-05-13 15 views
12

Se me ha recomendado usar las siguientes opciones con GCC, ya que ayuda a evitar muchos errores comunes. Enciende un montón de advertencias y -Werror las convierte en errores.¿Cómo puedo corregir advertencias como: "comparación entre firmado y sin firmar"?

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; 
} 

me sale esto:

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

Sé que una manera de que pueda solucionar este problema es apagar las advertencias, sino que haven' Me hizo usar estos ajustes para apagarlos al final.

Otra forma es lanzar las cosas, pero me han dicho que el casting está en desuso.

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

unsigned x; 

Pero esto no resuelve el problema general cuando tengo que comparar los valores firmados con valores sin signo utilizando estas opciones del compilador. ¿Hay una manera más limpia en lugar de lanzar?

+0

Tenga en cuenta que 'sizeof' devuelve' size_t' que debe imprimirse usando ['% zu'] (http://stackoverflow.com/q/940087/995714) –

Respuesta

4

Esto realmente depende del tipo de datos. Es posible evitar esto al convertir implícitamente los valores a un tipo que contiene un superconjunto de todos los valores disponibles en el tipo firmado y sin signo. Por ejemplo, podría usar un valor firmado de 64 bits para comparar un valor de 32 bits sin firmar y uno firmado.

Sin embargo, este es un caso de esquina y necesita 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.

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

Usted podría declarar ax como un entero sin signo, ya que no está firmado size_t

EDIT:

Si no desea emitir, y no desea declarar como no firmada, No creo que haya mucho que hacer.

Quizás las operaciones a nivel de bit sean una forma de resolverlo, eliminando el bit de signo. Debo decir que la OMI es muy cuestionable.

+0

" Pero no resuelve el problema general problema cuando tengo que comparar los valores firmados con los valores sin firmar con estas opciones de compilación. ¿Hay alguna forma más limpia de lanzar? " – George

+1

Hombre, ¿ha leído el final de la pregunta? – George

+0

sí.Pero la operación bit a bit * podría * considerarse * como un casting. – Tom

13

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 esto no resuelve el problema general cuando tengo que comparar los valores firmados con valores sin signo utilizando estas opciones del compilador. ¿Hay una forma más limpia de usar el casting?

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

+3

Estoy de acuerdo con esta respuesta. También tenga en cuenta que el casting no está en desuso, pero es probable que se desaconseje para un principiante, ya que puede llevarlo a algunos malos hábitos. – Borbus

+0

Esta es la mejor respuesta, pero introduzco un concepto de C++ en una pregunta acerca de C. No he usado la C estricta desde hace tiempo, pero no creo que puedas declarar tu variable de índice dentro del ciclo como lo haces en C++. –

+1

@Adrian McCarthy: Ver C99, 6.8.5.3.1: [...] "Si la cláusula-1 es una declaración , el alcance de cualquier identificador que declare es el resto de la declaración y el ciclo completo, incluido el otro dos expresiones; se alcanza en el orden de ejecución antes de la primera evaluación de la expresión de control. " – dirkgently

2

El quid de la cuestión es que la comparación de los valores firmados y no firmados admite algunos casos extraños. Considere, por ejemplo, que lo que ocurre en la longitud de matriz sin signo es mayor que el máximo que puede representarse con una int firmada. El desbordamiento del contador firmado (permaneciendo "menor que" el tamaño de la matriz), y usted comienza a direccionar la memoria que no pretendía ...

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

Sea riguroso al elegir la signadez de sus tipos, o anule el problema cuando esté seguro de que no se aplica, o deshágase de -Werror y establezca como política abordar todas las advertencias con una solución o un explicación ...

0

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

Puede hacer que los tipos estén de acuerdo (declarando variables para ser size_t o unsigned int en lugar de int, por ejemplo), o puede transmitir, o puede cambiar su línea de compilación. Eso es todo.

0

Independientemente del dilema de desaprovechamiento de fundición, aún así sugeriría separar la lógica del ciclo for.

int range = (int)(sizeof(arr)/sizeof(int)); 
int x; 

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

Aunque este utiliza colada que usted ha dicho está desfasada, se aclara la ubicación en la colada se lleva a cabo. En general, desaconsejo incluir mucha lógica en las declaraciones for loop. Especialmente en su caso donde está usando la división size_t, que (debido a que es una división entera) podría tener la posibilidad de truncar la respuesta. La declaración de bucle for debe estar limpia y no generar errores. Tu transmisión se produce en una ubicación diferente, lo que significa que si quieres cambiar la forma en que estás creando el rango, no tienes que preocuparte por hacer la declaración por más tiempo.

1

una opción sería la bandera adicional "-Wno-inicio de sesión comparar" :)

+0

Ocultar esta advertencia puede ocultar errores legítimos. –

+0

¡de ahí el emoticón! – frankster

1

Una solución sería la de desactivar selectivamente que una advertencia en este caso especial. GCC has pragma diagnostic ignored "-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 realmente seguro desde cuándo, pero 4.8.x debería apoyarlo) muestra la opción -Wsomething correspondiente. Esto es importante ya que la mayoría de las opciones de advertencia no están establecidas explícitamente, pero 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. */ 

El [-Werror = inscribirse comparar] parte te dice que puede utilizar "Wsign-comparar" para "Wsomething" suprimir la advertencia.

Y, por supuesto, sólo debe hacerlo donde sea apropiado (que no acaba de ayuda facilitar la lectura), por ejemplo, cuando se desea exactamente el comportamiento que el compilador advierte (o, si no puede introducir cambios más grandes en la base del código).

Cuestiones relacionadas