Ocasionalmente me encontraré con un tipo entero (por ejemplo, un entero POSIX con signo tipo off_t
) donde sería útil tener una macro para sus valores mínimo y máximo, pero no sé cómo hacer uno que sea verdaderamente portátil.Pregunta C: off_t (y otros tipos de entero con signo) valores mínimos y máximos
Para tipos de enteros sin signo, siempre había pensado que esto era simple. 0
para el mínimo y ~0
para el máximo. Desde entonces he leído varios hilos SO que sugieren usar -1
en lugar de ~0
para la portabilidad. Un hilo interesante con algo de contienda es aquí:
c++ - Is it safe to use -1 to set all bits to true? - Stack Overflow
Sin embargo, incluso después de leer sobre este tema todavía estoy confundido. Además, estoy buscando algo que cumpla con C89 y C99, así que no sé si se aplican los mismos métodos. Supongamos que tengo un tipo de uint_whatever_t
. ¿No podría simplemente convertir a 0 primero y luego a modo de complemento de bit? ¿Esto sería aceptable ?:
#define UINT_WHATEVER_T_MAX (~ (uint_whatever_t) 0)
tipo entero con signo parece que va a ser un hueso duro de roer. He visto varias soluciones posibles diferentes, pero solo one parece ser portátil. O eso o es incorrecto. Lo encontré mientras buscaba en Google un OFF_T_MAX y un OFF_T_MIN. Crédito a Christian Biere:
#define MAX_INT_VAL_STEP(t) \
((t) 1 << (CHAR_BIT * sizeof(t) - 1 - ((t) -1 < 1)))
#define MAX_INT_VAL(t) \
((MAX_INT_VAL_STEP(t) - 1) + MAX_INT_VAL_STEP(t))
#define MIN_INT_VAL(t) \
((t) -MAX_INT_VAL(t) - 1)
[...]
#define OFF_T_MAX MAX_INT_VAL(off_t)
no pude encontrar nada en relación con los diferentes tipos permitidos de representaciones de enteros con signo en C89, C99, pero tiene notas de problemas de portabilidad de números enteros en §J.3.5:
Si los tipos de entero con signo se representan mediante signo y magnitud, el complemento de dos , o el complemento de unos, y si el valor extraordinario es una representación de trap o un valor ordinario (6.2.6.2).
Eso parecería implicar que solo se pueden usar las tres representaciones de números con signo enumerados. ¿Es correcta la implicación y las macros anteriores son compatibles con las tres representaciones?
Otros pensamientos:
Parece que la función macro-como
MAX_INT_VAL_STEP()
darían un resultado incorrecto si hay bits de relleno. Me pregunto si hay alguna forma de evitar esto.
Lectura a través de signed number representations on Wikipedia se me ocurre que para las representaciones que los tres entero con signo de cualquier tipo entero con signo MAX sería:
poco fuera, todos los bits signo de valor sobre (los tres)
Y su MIN podría ser:
bit de signo en adelante, todos los bits de valor sobre (signo y magnitud)
bit de signo en adelante, todo valor de bits de apagado (los/complemento a dos)
creo que podría probar signo y magnitud al hacer esto:
#define OFF_T_MIN ((((off_t)1 | (~ (off_t) -1)) != (off_t)1) ? /* sign and magnitude minimum value here */ : /* ones and twos complement minimum value here */)
Entonces, como el signo y la magnitud es el bit de signo activado y todos los bits de valor activados, ¿no sería el mínimo para off_t en ese caso ~ (off_t) 0
? Y para el complemento de uno/dos al mínimo, necesitaría alguna forma de desactivar todos los bits de valor, pero dejar el bit de signo activado. No tengo idea de cómo hacer esto sin saber la cantidad de bits de valor. Además, ¿está garantizado que el bit de signo siempre será uno más significativo que el bit de valor más significativo?
Gracias y por favor, hágamelo saber si esto es demasiado tiempo un puesto
EDITAR 12/29/2010 17:00 EST:
Como contestado a continuación por ephemient para obtener el valor máximo de tipo sin signo, (unsigned type)-1
es más correcto que ~0
o incluso ~(unsigned type)0
. Por lo que puedo deducir cuando usas -1, es lo mismo que 0-1, que siempre llevará al valor máximo en un tipo sin firmar.
Además, como se puede determinar el valor máximo de un tipo sin signo, es posible determinar cuántos bits de valor están en un tipo sin signo. El crédito a Hallvard B. Furuseth por sus IMAX_BITS()-función como macro que se ha escrito en respuesta a una
IMAX_BITS (INT_MAX) calcula el número de bits en un int, y IMAX_BITS ((unsigned_type question on comp.lang.c
) -1) calcula el número de bits en unsigned_type. Hasta que alguien implementa enteros de 4 gigabytes, de todos modos :-)/* Number of bits in inttype_MAX, or in any (1<<b)-1 where 0 <= b < 3E+10 */ #define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \ + (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
El corazón de mi pregunta sin embargo sigue sin respuesta: ¿cómo determinar los valores mínimo y máximo de un firmó tipo a través de macro. Todavía estoy investigando esto. Quizás la respuesta es que no hay respuesta.
Si no está viendo esta pregunta en StackOverflow, en la mayoría de los casos no podrá ver las respuestas propuestas hasta que sean aceptadas. Se sugiere a view this question on StackOverflow.
De hecho, 'MAX_INT_VAL_STEP' se rompe si hay algunos bits de relleno. Tengo una pregunta relacionada a la que nunca obtuve una respuesta satisfactoria: http://stackoverflow.com/questions/3957252/is-there-any-way-to-compute-the-width-of-an-integer-type-at -compile-time –
@R ¿Qué plataformas apuntadas por un compilador de C tienen bits de relleno en los tipos integrales con signo? Tal vez se puedan manejar con algún '# ifdef' específico para esas plataformas, si es necesario. – Kaz