2010-01-13 113 views

Respuesta

78

Vas a querer 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 

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

Del mismo modo float.h establece los límites de float y double tipos:

-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 puede contener los valores máximo y mínimo prescrito y pero la precisión con la que cada tipo puede representar datos puede no coincidir con lo que está intentando almacenar. En particular, es difícil almacenar números excepcionalmente grandes con fracciones extremadamente pequeñas adjuntas. Por lo tanto, 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.

+1

¿Cuál es el valor mínimo y máximo de un flotador? – SuperString

+0

FLT_MAX y FLT_MIN –

+2

'SIZE_MAX' (tamaño máximo de' size_t') es otro útil. – caf

3

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

+0

¿cuál es el valor mínimo de char sin signo? – SuperString

+4

@Superstring, el valor mínimo de cualquier tipo * unsigned * es 0. –

+4

¡Quiero valores negativos sin signo! :-) –

3

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

23

"Pero glifo", te escucho preguntar, "¿qué pasa 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 haya 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 práctica 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))) 

Se puede utilizar de este modo:

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 desea, puede lanzar una '(t)' en la parte frontal de las macros lo que le dará un resultado de la escribe lo que estás preguntando, y no tienes que hacer casting para evitar advertencias.

+0

¿No '~ ((t) 0)' funcionaría para un máximo de unsigned? (no es así, pero todavía no estoy seguro de por qué). – Gauthier

+0

Bueno, funciona, pero requiere el tipo de transmisión que mencionaste. – Gauthier

+0

[Cómo detectar si el tipo está firmado] (http://stackoverflow.com/a/7470062/991816) – DanSkeel

3

I escribió algunos macros que retornan el min y max de cualquier tipo, independientemente de de signo:

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

valores MIN y MAX de cualquier tipo de datos entero puede haber computar sin usar ninguna función de biblioteca como la de abajo 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)); 
4

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

Valor máximo de cualquier firmado integral de tipo: Si usted tiene una variante sin signo de tipo T, ((t)((~(unsigned t)0)>>1)) te 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 firmado : Usted tiene que saber la representación número con signo 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 un complemento de 2, detectar 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 de complemento de 2. Por ejemplo, (t)(1ULL<<(sizeof(t)*CHAR_BIT-1)) debe 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 se SIZE_MAX #defined en Linux kernel source code.)

Una salvedad aunque: todas estas expresiones utilizan la conversión de tipos y por lo tanto no funcionan en condicionales del preprocesador (#if ... #elif ... #endif y me gusta).

0

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 de enteros): ~(t) 0.

Si el tipo de número entero t está firmado, suponiendo que no hay bits de relleno, se puede utilizar:

((((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 posible en la práctica, simplemente para facilitar la lectura):

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

en complemento a dos, el valor mínimo es el contrario del valor máximo, menos 1 (en las otras representaciones de números enteros permitido por el ISO C estándar, esto es exactamente lo opuesto al valor máximo).

3
#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; 
} 
+0

Simplemente podemos obtener el valor más alto del tipo de datos sin firmar y restarlo del valor máximo para obtener el valor mínimo. –

+0

Esta es una excelente respuesta independiente del sistema que demuestra una comprensión de los tipos, la memoria y, por supuesto, de los operadores de bit a bit de C. –

Cuestiones relacionadas