valor mínimo y máximo del tipo de datos en C


¿Cuál es la función para determinar el valor mínimo y máximo posible de los tipos de datos (es decir, int, char.etc) en C?

 65
Author: Eric Leschinski, 2010-01-13

9 answers

Usted querrá usar limits.h que proporciona las siguientes constantes (según la referencia vinculada):

CHAR_BIT   = number of bits in a char
SCHAR_MIN  = minimum value for a signed char
SCHAR_MAX  = maximum value for a signed char
UCHAR_MAX  = maximum value for an unsigned char
CHAR_MIN   = minimum value for a char
CHAR_MAX   = maximum value for a char
MB_LEN_MAX = maximum multibyte length of a character accross locales
SHRT_MIN   = minimum value for a short
SHRT_MAX   = maximum value for a short
USHRT_MAX  = maximum value for an unsigned short
INT_MIN    = minimum value for an int
INT_MAX    = maximum value for an int
UINT_MAX   = maximum value for an unsigned int
LONG_MIN   = minimum value for a long
LONG_MAX   = maximum value for a long
ULONG_MAX  = maximum value for an unsigned long
LLONG_MIN  = minimum value for a long long
LLONG_MAX  = maximum value for a long long
ULLONG_MAX = maximum value for an unsigned long long

Donde U*_MIN se omite por razones obvias (cualquier tipo sin signo tiene un valor mínimo de 0).

Del mismo modo float.h proporciona límites para los tipos float y double:

-FLT_MAX = most negative value of a float
FLT_MAX  = max value of a float
-DBL_MAX = most negative value of a double
DBL_MAX  = max value of a double
-LDBL_MAX = most negative value of a long double
LDBL_MAX = max value of a long double

Debe leer el artículo sobre floats.h cuidadosamente, aunque float y double pueden contener los valores mínimos y máximos prescritos, pero la precisión con la que cada tipo puede es posible que los datos de representación no coincidan con lo que está tratando de almacenar. En particular, es difícil almacenar números excepcionalmente grandes con fracciones extremadamente pequeñas unidas. Así que float.h proporciona un número de otras constantes que le ayudan a determinar si un float o un double puede,de hecho,representar un número particular.

 82
Author: Mark Elliot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-18 02:38:45

"Pero glifo", te oigo preguntar, "¿qué pasa si tengo que determinar el valor máximo para un tipo opaco cuyo máximo podría cambiar eventualmente?"Podría continuar:" ¿Qué pasa si es un typedef en una biblioteca que no controlo?"

Me alegro de que hayas preguntado, porque acabo de pasar un par de horas cocinando una solución (que luego tuve que tirar, porque no resolvió mi problema real).

Puede usar esta práctica macro maxof para determinar el tamaño de cualquier entero válido tipo.

#define issigned(t) (((t)(-1)) < ((t) 0))

#define umaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \
                    (0xFULL << ((sizeof(t) * 8ULL) - 4ULL)))

#define smaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \
                    (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL)))

#define maxof(t) ((unsigned long long) (issigned(t) ? smaxof(t) : umaxof(t)))

Puedes usarlo así:

int main(int argc, char** argv) {
    printf("schar: %llx uchar: %llx\n", maxof(char), maxof(unsigned char));
    printf("sshort: %llx ushort: %llx\n", maxof(short), maxof(unsigned short));
    printf("sint: %llx uint: %llx\n", maxof(int), maxof(unsigned int));
    printf("slong: %llx ulong: %llx\n", maxof(long), maxof(unsigned long));
    printf("slong long: %llx ulong long: %llx\n",
           maxof(long long), maxof(unsigned long long));
    return 0;
}

Si lo desea, puede lanzar una '(t)' al frente de esas macros para que le den un resultado del tipo que está preguntando, y no tiene que hacer casting para evitar advertencias.

 25
Author: Glyph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-27 00:08:48

Valor máximo de cualquier tipo de integral sin signo : (~(t)0)

Valor máximo de cualquier tipo integral con signo: Si tiene una variante sin signo del tipo t, ((t)((~(unsigned t)0)>>1)) le dará el resultado más rápido que necesita (vea el ejemplo en el código fuente del kernel de Linux al que se hace referencia a continuación). De lo contrario, probablemente debería usar (~(1ULL<<(sizeof(t)*CHAR_BIT-1))).

Valor mínimo de cualquier tipo integral con signo : Debe conocer la representación numérica con signo de su equipo. La mayoría de las máquinas usan el complemento de 2, por lo que -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1 funcionará para usted.

Para detectar si su máquina utiliza el complemento de 2, detecte si (~(t)0U) y (t)(-1) representan la misma cosa. Así, combinado con lo anterior:

((~(t)0U) == (t)(-1) ? -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1 :
                       -(~(1ULL<<(sizeof(t)*CHAR_BIT-1))))

Le dará el valor mínimo de cualquier tipo integral con signo. (En realidad hay otras representaciones de esto si conoces la representación del complemento de 2. Por ejemplo, (t)(1ULL<<(sizeof(t)*CHAR_BIT-1)) debería ser equivalente a (t)(-(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1).)

Por ejemplo: (~(size_t)0) le da la valor máximo de size_t. (Y adivina qué, así es como se define SIZE_MAX #en el código fuente del kernel de Linux .)

Una advertencia sin embargo: todas estas expresiones usan tipo casting y por lo tanto no funcionan en condicionales preprocesadores (#if ... # elif ... # endif and like).

 5
Author: Explorer09,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-09 01:25:49

Mira estas páginas en límites.h y flotan.h, que se incluyen como parte de la biblioteca estándar de c.

 3
Author: Nixuz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-13 01:45:34

Escribí algunas macros que devuelven el mínimo y el máximo de cualquier tipo, independientemente de la signedness:

#define MAX_OF(type) \
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU))
#define MIN_OF(type) \
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL)

Código de ejemplo:

#include <stdio.h>
#include <sys/types.h>
#include <inttypes.h>

#define MAX_OF(type) \
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU))
#define MIN_OF(type) \
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL)

int main(void)
{
    printf("uint32_t = %lld..%llu\n", MIN_OF(uint32_t), MAX_OF(uint32_t));
    printf("int32_t = %lld..%llu\n", MIN_OF(int32_t), MAX_OF(int32_t));
    printf("uint64_t = %lld..%llu\n", MIN_OF(uint64_t), MAX_OF(uint64_t));
    printf("int64_t = %lld..%llu\n", MIN_OF(int64_t), MAX_OF(int64_t));
    printf("size_t = %lld..%llu\n", MIN_OF(size_t), MAX_OF(size_t));
    printf("ssize_t = %lld..%llu\n", MIN_OF(ssize_t), MAX_OF(ssize_t));
    printf("pid_t = %lld..%llu\n", MIN_OF(pid_t), MAX_OF(pid_t));
    printf("time_t = %lld..%llu\n", MIN_OF(time_t), MAX_OF(time_t));
    printf("intptr_t = %lld..%llu\n", MIN_OF(intptr_t), MAX_OF(intptr_t));
    printf("unsigned char = %lld..%llu\n", MIN_OF(unsigned char), MAX_OF(unsigned char));
    printf("char = %lld..%llu\n", MIN_OF(char), MAX_OF(char));
    printf("uint8_t = %lld..%llu\n", MIN_OF(uint8_t), MAX_OF(uint8_t));
    printf("int8_t = %lld..%llu\n", MIN_OF(int8_t), MAX_OF(int8_t));
    printf("uint16_t = %lld..%llu\n", MIN_OF(uint16_t), MAX_OF(uint16_t));
    printf("int16_t = %lld..%llu\n", MIN_OF(int16_t), MAX_OF(int16_t));
    printf("int = %lld..%llu\n", MIN_OF(int), MAX_OF(int));
    printf("long int = %lld..%llu\n", MIN_OF(long int), MAX_OF(long int));
    printf("long long int = %lld..%llu\n", MIN_OF(long long int), MAX_OF(long long int));
    printf("off_t = %lld..%llu\n", MIN_OF(off_t), MAX_OF(off_t));

    return 0;
}
 3
Author: craig65535,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-05 18:01:17

El archivo de cabeceralimits.h define macros que se expanden a varios límites y parámetros de los tipos enteros estándar.

 3
Author: Prasoon Saurav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-20 20:33:23
#include<stdio.h>

int main(void)
{
    printf("Minimum Signed Char %d\n",-(char)((unsigned char) ~0 >> 1) - 1);
    printf("Maximum Signed Char %d\n",(char) ((unsigned char) ~0 >> 1));

    printf("Minimum Signed Short %d\n",-(short)((unsigned short)~0 >>1) -1);
    printf("Maximum Signed Short %d\n",(short)((unsigned short)~0 >> 1));

    printf("Minimum Signed Int %d\n",-(int)((unsigned int)~0 >> 1) -1);
    printf("Maximum Signed Int %d\n",(int)((unsigned int)~0 >> 1));

    printf("Minimum Signed Long %ld\n",-(long)((unsigned long)~0 >>1) -1);
    printf("Maximum signed Long %ld\n",(long)((unsigned long)~0 >> 1));

    /* Unsigned Maximum Values */

    printf("Maximum Unsigned Char %d\n",(unsigned char)~0);
    printf("Maximum Unsigned Short %d\n",(unsigned short)~0);
    printf("Maximum Unsigned Int %u\n",(unsigned int)~0);
    printf("Maximum Unsigned Long %lu\n",(unsigned long)~0);

    return 0;
}
 3
Author: rahul gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-21 15:40:20

Los valores MÍNIMOS y MÁXIMOS de cualquier tipo de datos enteros se pueden calcular sin usar ninguna función de biblioteca como se muestra a continuación y la misma lógica se puede aplicar a otros tipos enteros cortos, int y largos.

printf("Signed Char : MIN -> %d & Max -> %d\n", ~(char)((unsigned char)~0>>1), (char)((unsigned char)~0 >> 1));
printf("Unsigned Char : MIN -> %u & Max -> %u\n", (unsigned char)0, (unsigned char)(~0));
 0
Author: Arjun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-27 16:05:41

Para obtener el valor máximo de un entero sin signo escriba t cuyo ancho es al menos el de unsigned int (de lo contrario se obtienen problemas con promociones de enteros): ~(t) 0. Si uno quiere también soportar tipos más cortos, se puede añadir otro cast: (t) ~(t) 0.

Si el tipo entero t está firmado, suponiendo que no hay bits de relleno, se puede usar:

((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1)

La ventaja de esta fórmula es que no se basa en alguna versión sin signo de t (o un tipo más grande), que puede ser desconocido o no disponible (incluso uintmax_t puede no ser suficiente con extensiones no estándar). Ejemplo con 6 bits (no es posible en la práctica, solo por legibilidad):

010000  (t) 1 << (sizeof(t) * CHAR_BIT - 2)
001111  - 1
011110  * 2
011111  + 1

En el complemento two, el valor mínimo es el opuesto del valor máximo, menos 1 (en las otras representaciones de enteros permitidas por el estándar ISO C, esto es justo lo contrario del valor máximo).

Nota: Para detectar signedness con el fin de decidir qué versión utilizar: (t) -1 < 0 funcionará con cualquier entero representación, dando 1 (verdadero) para los tipos enteros con signo y 0 (falso) para los tipos enteros sin signo. Así se puede usar:

(t) -1 < 0 ? ((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1) : (t) ~(t) 0
 0
Author: vinc17,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-13 07:53:08