El estándar C garantiza que size_t
es un tipo que puede contener cualquier índice de matriz. Esto significa que, lógicamente, size_t
debería ser capaz de contener cualquier tipo de puntero. He leído en algunos sitios que he encontrado en los Googles que esto es legal y/o debe trabajar siempre:size_t contra uintptr_t
void *v = malloc(10);
size_t s = (size_t) v;
Así que en C99, la norma introduce las intptr_t
y uintptr_t
tipos, que son firmados y no firmados tipos garantizados para ser capaz de mantener los punteros:
uintptr_t p = (size_t) v;
Entonces, ¿cuál es la diferencia entre usar size_t
y uintptr_t
? Ambos no tienen firma, y ambos deberían ser capaces de contener cualquier tipo de puntero, por lo que parecen funcionalmente idénticos. ¿Hay alguna razón convincente real para usar uintptr_t
(o mejor aún, un void *
) en lugar de un size_t
, que no sea claridad? En una estructura opaca, donde el campo será manejado solo por funciones internas, ¿hay alguna razón para no hacer esto?
De la misma manera, ptrdiff_t
ha sido un tipo firmado capaz de contener las diferencias de puntero, y por lo tanto capaz de contener la mayoría de los punteros, entonces ¿cómo es distinto de intptr_t
?
¿No son básicamente todos estos tipos que sirven versiones triviales diferentes de la misma función? Si no, ¿por qué? ¿Qué no puedo hacer con uno de ellos que no puedo hacer con otro? Si es así, ¿por qué C99 agregó dos tipos esencialmente superfluos al lenguaje?
Estoy dispuesto a ignorar los indicadores de función, ya que no se aplican al problema actual, pero siéntete libre de mencionarlos, ya que tengo la sospecha de que serán fundamentales para la respuesta "correcta".
Esto, junto con muchos otros que saltaron a la misma conclusión, explica la diferencia entre 'size_t' y' uintptr_t', pero ¿qué pasa con 'ptrdiff_t' y' intptr_t'? ¿No podrían estos dos almacenar el mismo rango? de valores en casi cualquier plataforma? ¿Por qué tienen tipos de enteros con tamaño de puntero tanto firmados como no firmados, especialmente si 'ptrdiff_t' ya sirve para un tipo de entero con el tamaño de puntero firmado. –
Frase clave hay "en * casi * cualquier plataforma", @Chris. Una implementación es libre de restringir los punteros al rango 0xf000-0xffff; esto requiere un intptr_t de 16 bits, pero solo un ptrdiff_t de 12/13 bits. – paxdiablo
@Chris, solo para punteros _inside the same array_ está bien definido para tomar su diferencia. Por lo tanto, exactamente en las mismas arquitecturas segmentadas de 16 bits (la matriz debe vivir dentro de un solo segmento pero dos arreglos diferentes pueden estar en segmentos diferentes) los punteros deben ser de 4 bytes, ¡pero las ** diferencias ** del puntero podrían ser de 2 bytes! –