tipos tipo sirve rangos que primitivos para long derivados datos dato c types

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



unsigned char c (9)

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

Me alegra que me 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 utilizar esta útil macro maxof para determinar el tamaño de cualquier tipo de entero válido.

#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 un ''(t)'' al frente de esas macros para que le den el resultado del tipo sobre el que está preguntando, y no tiene que hacer un casting para evitar advertencias.

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


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


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

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


Los valores MIN y MAX de cualquier tipo de datos enteros se pueden calcular sin utilizar ninguna función de biblioteca como la siguiente 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));


Mire estas páginas en limits.h y float.h , que se incluyen como parte de la biblioteca c estándar.


Para obtener el valor máximo de un entero sin signo, escriba t cuyo ancho sea al menos el de unsigned int (de lo contrario, se obtienen problemas con las promociones enteras): ~(t) 0 . Si uno quiere también soportar tipos más cortos, uno puede agregar otro molde: (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 una versión sin firmar de t (o un tipo más grande), que puede ser desconocida o no estar 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 para la legibilidad):

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

En el complemento a dos, el valor mínimo es el opuesto al valor máximo, menos 1 (en las otras representaciones enteras permitidas por el estándar ISO C, esto es exactamente lo opuesto al valor máximo).

Nota: Para detectar firmados para decidir qué versión usar: (t) -1 < 0 funcionará con cualquier representación entera, dando 1 (verdadero) para tipos enteros con signo y 0 (falso) para tipos enteros sin signo. Por lo tanto, uno puede usar:

(t) -1 < 0 ? ((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1) : (t) ~(t) 0


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

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

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

Para detectar si su máquina usa el complemento 2, detecte si (~(t)0U) y (t)(-1) representan lo mismo. Entonces, 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 firmado. (De hecho, hay otras representaciones de esto si conoce 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 el valor máximo de size_t. (Y adivina qué, así es como SIZE_MAX está # definido en el código fuente del kernel de Linux ).

Sin embargo, una advertencia : todas estas expresiones utilizan el tipo de conversión y, por lo tanto, no funcionan en los condicionales del preprocesador (#if ... #elif ... #endif y similares).


Deberá usar limits.h que proporcione las siguientes constantes (según la referencia enlazada):

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 limits.h modo, limits.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

Debes leer el artículo en 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 representar datos puede no coincidir con lo que estás intentando almacenar. En particular, es difícil almacenar números excepcionalmente grandes con fracciones extremadamente pequeñas adjuntas. Entonces float.h proporciona varias otras constantes que lo ayudan a determinar si un float o un double pueden, de hecho, representar un número en particular.


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