variable tipos tipo sirve rangos que programacion para float datos dato c

c - tipos - unsigned int para que sirve



Desbordamiento aparece incluso cuando se usa int largo sin firmar (5)

El desbordamiento se produce antes de que se asigne un valor a la variable. Para evitar ese uso sufijo largo y largo:

60123456LL * 128 * sizeof(double)

(los comentarios también sugieren ULL, que no es necesario aquí porque los valores están dentro del rango firmado, pero esa sería la forma genérica de hacerlo)

Cuando hago el siguiente cálculo:

unsigned long long int data_size = 60123456 * 128 * sizeof(double); printf("data_size= %llu /n", data_size);

Sorprendentemente recibo advertencia de desbordamiento:

test.c:20:49: warning: overflow in expression; result is -894132224 with type ''int'' [-Winteger-overflow] unsigned long long int data_size = 60123456 * 128 * sizeof(double); ^ 1 warning generated.

¡No puedo entender por qué aparece este error aunque estoy usando unsigned long long int ! ¿Alguien puede explicar por qué? Gracias


El lexer 5.1.1.2 Translation phases tipos en constantes durante la fase de traducción 7 (conversión de tokens de preprocesamiento en tokens C). Cf 5.1.1.2 Translation phases 5.1.1.2 5.1.1.2 Translation phases . Como dijeron los demás, el lexer adjuntará a sus constantes el tipo int lugar de unsigned long long que desee, y para que las default arithmetic conversions generen una constante de tipo unsigned long long en el lado derecho de la tarea que necesita para decirle al lexer que agregue el tipo unsigned long long por lo menos en una constante de la operación * que genera el desbordamiento, por lo tanto, escriba 60123456ULL * 128 o 60123456 * 128ULL o ambos.


Estás convirtiendo a "largo" demasiado tarde. 60123456 * 128 sigue siendo una expresión int que desborda.

Intente 60123456LL * 128 lugar. (LL porque no se garantiza que el valor resultante se ajuste a un largo).


Las constantes 60123456 y 128 son de tipo int , por lo tanto, la expresión 60123456 * 128 también es de tipo int . El valor de esta expresión desbordaría el rango de un int . El compilador es capaz de detectarlo en este caso porque ambos operandos son constantes.

Debe usar el sufijo ULL en el primer operando para hacer que el tipo de constante unsigned long long . De esa manera coincide con el tipo al que está asignado. Luego, para cualquier operación que involucre este valor, el otro operando será promovido a unsigned long long antes de que se aplique la operación y no tendrá ningún desbordamiento.

Entonces la expresión resultante debería verse así:

unsigned long long int data_size = 60123456ULL * 128 * sizeof(double);


unsigned long long int data_size = 60123456 * 128 * sizeof(double); // trouble-some code

El tipo de destino unsigned long long int data_size = no es relevante para el cálculo del producto 60123456 * 128 * sizeof(double) .

Lo mejor para asegurar que las matemáticas se realicen utilizando al menos el tamaño del tipo de destino para evitar el desbordamiento. En el caso de OP, eso implica una constante con LLU .

Hay 2 cálculos de productos, cada uno con su propio tipo matemático.

60123456 es un int o long dependiendo del rango int . Supongamos que es un int .

60123456 * 128 es un int * int . El producto matemático 7695802368 excede el rango de entero con signo de 32 bits, por lo tanto, desbordamiento de entero con signo o comportamiento indefinido (UB) con un int 32 bits.

Si 60123456 * 128 no se desbordara, dice int 64 bits, entonces la siguiente multiplicación sería * sizeof(double); y así int * size_t da como resultado un producto de tipo size_t .

El cálculo del producto debe utilizar, al menos, cálculos matemáticos unsigned long long como se muestra a continuación:

unsigned long long int data_size = 1LLU * 60123456 * 128 * sizeof(double); // or unsigned long long int data_size = 60123456LLU * 128 * sizeof(double); // or unsigned long long int data_size = 60123456; data_size *= 128 * sizeof(double); // or avoiding naked magic numbers #define A_HEIGHT 60123456 #define A_WIDTH 128 unsigned long long int data_size = 1LLU * A_HEIGHT * A_WIDTH * sizeof(double);

El tamaño de sizeof (double) insinúa que el código está intentando encontrar el tamaño de alguna estructura similar a 2D. Yo esperaría un código como el siguiente. Observe que el tipo de resultado de sizeof es size_t , por lo que la matemática del producto se realiza utilizando al menos size_t math.

size_t data_size = sizeof(double) * 60123456 * 128; printf("data_size= %zu/n", data_size);

Consulte también ¿Por qué escribir 1,000,000,000 como 1000 * 1000 * 1000 en C? y mi respuesta es una razón para no usar 1000 * 1000 * 1000 para detalles aplicables.