2010-02-28 15 views
12

Tengo la siguiente matriz, que necesito para operar a mano en bitmaps.C++: advertencia del compilador para gran unsigned int

const unsigned int BITS[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
           2048, 4096, 8192, 16384, 32768, 65536, 131072, 
           262144, 524288, 1048576, 2097152, 4194304, 
           8388608, 16777216, 33554432, 67108864, 134217728, 
           268435456, 536870912, 1073741824, 2147483648}; 

Por desgracia, cuando se compila me sale

advertencia: esta constante decimal es sin firmar sólo en ISO C90

¿Cómo puedo quitar esto?

+0

Ver esta pregunta similar: http://stackoverflow.com/questions/2347936/cant-get-ride-of-this-decimal-constant -is-unsigned-only-in-iso-c90-warning –

+0

¿Por qué estás haciendo esto? Si crees que una tabla de búsqueda va a ser más rápida que simplemente calcular estos valores según sea necesario, piénsalo de nuevo ... – Nemo

Respuesta

15

Los literales enteros en C son, por defecto, del tipo "signed int" (edit: pero vea los comentarios para las advertencias). El último número no es demasiado grande para representarse como un entero de 32 bits con signo, y por lo que necesita para decirle al compilador que es un entero sin signo sufijando con "T", como:

2147483648U 

Tenga en cuenta que también puede agregar un sufijo de "L" para que sea "largo", pero en muchos sistemas todavía es de 32 bits y por lo tanto irrelevante.

Además, hay una manera mucho menos propenso a errores (y más fácil de leer) para escribir el código, con el operador de desplazamiento de bit:

const unsigned int BITS[32] = {1U, 1U<<1, 1U<<2, 1U<<3, 1U<<4, 
           /* and so on */ 
           1U<<31}; 

O, escribiendo en hexadecimal, si no no me gustan los cambios de bit por alguna razón:

const unsigned int BITS[32] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 
           /* and so on */ 
           0x80000000U}; 
+0

¿Por qué el compilador lo trata entonces como un int, en lugar de convertirlo automáticamente en uint? Especialmente, que sabe exactamente en qué tipo se almacenará. – gruszczy

+0

En muchos casos no se puede saber qué tipo es una constante (por ejemplo, como un argumento de función en una función varargs) por lo que debe especificarse explícitamente. Es confuso hacer que el tipo sea implícito algunas veces y deba especificarse explícitamente en otros, y también confuso tener la misma constante en diferentes tipos de sistemas con diferentes tamaños int. Además, dado que C nunca hace una inferencia de ese tipo, agregarla para este caso complicaría mucho el analizador sin un beneficio significativo. –

+3

@gruszczy: en C89/90, una constante decimal sin fundir debe interpretarse como 'int',' long' o 'unsigned long' (lo que corresponda primero). En C99, debe interpretarse como 'int',' long' o 'long long' (lo que corresponda primero). Esto es lo que el compilador está tratando de decir con esta advertencia. Aparentemente, en esta plataforma 'long' tiene el mismo tamaño que' int'. El compilador básicamente dice: "tal vez estabas tratando de crear un connstant 'signed long' o incluso una constante 'long long', pero según las reglas C89/90 tengo que hacerlo' unsigned long '. – AnT

6

Su constante tiene que ser especificado como no firmada también, utilizar

2147483648UL 

(UL = largo sin signo), o simplemente

2147483648U 

para un unsigned int.

Como su código es ahora mismo, una constante, que por defecto es int y, por lo tanto, firmada, se asigna a unsigned int, que genera su advertencia.

+0

Eso funcionó, muchas gracias :-) – gruszczy

+3

Pedadicamente hablando, el error no es por el hecho de que int) constant se asigna a unsigned int; la asignación es irrelevante. El error se debe a que el valor de "2147483648" es demasiado grande para ser un int firmado, por lo que hay un desbordamiento al generar la constante int firmada en primer lugar. –

+2

En realidad, la verdadera razón de la advertencia es que el compilador tiene que elegir 'unsigned long' para el tipo constante. (Nota, de nuevo, esta constante no es 'unsigned int', es' unsigned long'.) Y tiene que elegirla en C89/90 específicamente, en lugar de elegir un tipo más grande con signo (que podría ser compatible) o seguir a C99 reglas y elegir 'long long'. De esto se trata la advertencia y por qué se refiere a 'ISO C90'. En C99, por ejemplo, una constante decimal no enriquecida nunca recibiría un tipo sin signo. – AnT

1

No es necesario para definir el tipo de datos como sin firmar simplemente escriba;

int variable_name=2147483648U; 

demás sólo convertir el valor decimal a hexadecimal ...

Cuestiones relacionadas