2010-02-14 20 views
5

¿Los desajustes con o sin firma son necesariamente malos?C89: discrepancia entre firma/no firma

Aquí es mi programa:

int main(int argc, char *argv[]) { 
    unsigned int i; 

    for (i = 1; i < argc; i++) { // signed/unsigned mismatch here 

    } 
} 

argc está firmado, i no lo es. ¿Es esto un problema?

+0

No es un engaño, pero vale la pena leerlo de todos modos: http://stackoverflow.com/questions/859943/c-how-can-fix-warnings-like-comparison-between-signed-and-unsigned – finnw

Respuesta

9

"desacuerdos con o sin firma" puede ser malo. En su pregunta, usted está preguntando acerca de las comparaciones. Al comparar dos valores del mismo tipo de base, pero uno firmado y otro sin firmar, el valor firmado se convierte en sin firmar. Así,

int i = -1; 
unsigned int j = 10; 

if (i < j) 
    printf("1\n"); 
else 
    printf("2\n"); 

impresiones 2 y no por 1. Esto es porque en i < j, i se convierte en un unsigned int. (unsigned int)-1 es igual a UINT_MAX, un número muy grande. La condición así se evalúa como falsa, y se llega a la cláusula else.

Para su ejemplo particular, argc se garantiza que no es negativo, por lo que no tiene que preocuparse por la "falta de coincidencia".

+0

why firmado convertido a unsigned (¿por qué no viceversa)? este comportamiento estandarizado? – triclosan

+0

@triclosan, sí. Las reglas son un poco complejas, pero para 'int' y' unsigned int', ya que tienen el mismo rango, el tipo con signo se convierte al tipo sin signo. Ver la sección 6.3.1.8 de N1256 para más detalles. –

1

No es un problema real en su caso particular, pero el compilador no puede saber que argc siempre tendrá valores que no causarán ningún problema.

+0

Si 'argc' es demasiado grande para caber en un' int', de todos modos tienes serios problemas :-) – finnw

+0

No necesariamente. 'INT_MAX' puede ser tan bajo como 32767 y he visto líneas de comando que exceden varios cientos de kilobytes. Se sabe que la utilidad xargs (1) alcanza fácilmente ese límite. – Jens

1

Es solo un problema indirecto.

cosas malas pueden suceder si utiliza enteros con signo para operaciones bit a bit como &, |, << y >>.
cosas malas pueden suceder completamente diferente si se utiliza enteros sin signo para la aritmética (flujo inferior, bucles infinitos al probar si un número es >= 0 etc.)

Debido a esto, algunos compiladores y herramientas de comprobación estática emitirán advertencias cuando se mezclan enteros con signo y sin signo en cualquier tipo de operación (aritmética o manipulación de bits)

Aunque puede ser seguro mezclarlos en casos simples como en el ejemplo, si lo hace significa que no puede usar esas herramientas de comprobación estáticas (o debe desactivar esas advertencias) lo que puede significar que otros errores no se detecten.

A veces no tiene otra opción, p. al hacer aritmética en valores de tipo size_t en código de gestión de memoria.

En el ejemplo que se pegaba a int, simplemente porque es más simple de tener un menor número de tipos y el int va a ser allí de todos modos ya que es el tipo del primer argumento para main().

1

No está mal. Arreglaría las advertencias del compilador con respecto al desajuste firmado/no firmado porque pueden suceder cosas malas, incluso si son poco probables o imposibles. Cuando tiene que corregir un error debido a falta de coincidencia con firma/sin firma, el compilador básicamente dice "se lo dije". No ignore la advertencia allí por una razón.

Cuestiones relacionadas