Necesitamos tu apoyo para difundir nuestras crónicas acerca de las ciencias informáticas.
Solución:
Querrás usar limits.h
que proporciona las siguientes constantes (según la referencia vinculada):
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
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
PTRDIFF_MIN : minimum value of ptrdiff_t
PTRDIFF_MAX : maximum value of ptrdiff_t
SIZE_MAX : maximum value of size_t
SIG_ATOMIC_MIN : minimum value of sig_atomic_t
SIG_ATOMIC_MAX : maximum value of sig_atomic_t
WINT_MIN : minimum value of wint_t
WINT_MAX : maximum value of wint_t
WCHAR_MIN : minimum value of wchar_t
WCHAR_MAX : maximum value of wchar_t
CHAR_BIT : number of bits in a char
MB_LEN_MAX : maximum length of a multibyte character in bytes
Donde U*_MIN
se omite por razones obvias (cualquier tipo sin firmar tiene un valor mínimo de 0).
similar float.h
proporciona límites para float
y double
tipos:
FLT_MIN : smallest normalised positive value of a float
FLT_MAX : largest positive finite value of a float
DBL_MIN : smallest normalised positive value of a double
DBL_MAX : largest positive finite value of a double
LDBL_MIN : smallest normalised positive value of a long double
LDBL_MAX : largest positive finite value of a long double
FLT_DIG : the number of decimal digits guaranteed to be preserved converting from text to float and back to text
DBL_DIG : the number of decimal digits guaranteed to be preserved converting from text to double and back to text
LDBL_DIG : the number of decimal digits guaranteed to be preserved converting from text to long double and back to text
Los tipos de punto flotante son simétricos alrededor de cero, por lo que el número finito más negativo es la negación del número finito más positivo, por ejemplo float
rangos desde -FLT_MAX
para FLT_MAX
.
Tenga en cuenta que los tipos de punto flotante solo pueden representar exactamente un número pequeño y finito de valores dentro de su rango. A medida que los valores absolutos almacenados se hacen más grandes, el espacio entre números adyacentes que se pueden representar exactamente también se hace más grande.
“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 eventualmente?” Puede 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 preparando una solución (que luego tuve que tirar porque no resolvió mi problema real).
Puedes usar esto a mano maxof
macro para determinar el tamaño de cualquier tipo 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: %llxn", maxof(char), maxof(unsigned char));
printf("sshort: %llx ushort: %llxn", maxof(short), maxof(unsigned short));
printf("sint: %llx uint: %llxn", maxof(int), maxof(unsigned int));
printf("slong: %llx ulong: %llxn", maxof(long), maxof(unsigned long));
printf("slong long: %llx ulong long: %llxn",
maxof(long long), maxof(unsigned long long));
return 0;
Si lo desea, puede agregar una '(t)' al frente de esas macros para que le brinden un resultado del tipo que está preguntando, y no tiene que hacer una conversión para evitar advertencias.
Máximo valor de cualquier no firmado tipo integral:
-
((t)~(t)0)
// Expresión genérica que funcionaría en casi todas las circunstancias. -
(~(t)0)
// Si conoces tu tipot
tener un tamaño igual o mayor que
unsigned int
. (Este elenco fuerza la promoción de tipos). -
((t)~0U)
// Si conoces tu tipot
tener un tamaño más pequeño que
unsigned int
. (Este elenco degrada el tipo después delunsigned int
-expresión de tipo~0U
se evalúa.)
Máximo valor de cualquier firmado tipo integral:
-
Si tiene una variante sin firmar de tipo
t
,((t)(((unsigned t)~(unsigned t)0)>>1))
le daría el resultado más rápido que necesita. -
De lo contrario, use esto (gracias a @ vinc17 por la sugerencia):
(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)
Mínimo valor de cualquier firmado tipo integral:
Tienes que saber la representación del número con signo de tu máquina. La mayoría de las máquinas utilizan el complemento a 2, por lo que -(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-1
funcionará para usted.
Para detectar si su máquina usa complemento a 2, detecte si (~(t)0U)
y (t)(-1)
representar lo mismo.
Entonces, combinado con lo anterior:
(-(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-(((~(t)0U)==(t)(-1)))
le dará el valor mínimo de cualquier tipo integral con signo.
Como ejemplo: Valor máximo de size_t
(también conocido como el SIZE_MAX
macro) Puede ser definido como (~(size_t)0)
. Definición del código fuente del kernel de Linux SIZE_MAX
macro Por aquí.
Una advertencia aunque: todas estas expresiones usan conversión de tipos o sizeof
operador y, por lo tanto, ninguno de estos funcionaría en condicionales de preprocesador (#if
... #elif
... #endif
y, como).
(Respuesta actualizada para incorporar sugerencias de @ chux y @ vinc17. Gracias a ambos).
Nos puedes asentar nuestro ensayo dejando un comentario y puntuándolo te estamos eternamente agradecidos.