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 poder contener cualquier tipo de puntero. Leí en algunos sitios que encontré en Google que esto es legal y / o siempre debería funcionar:
void *v = malloc(10);
size_t s = (size_t) v;
Entonces, en C99, el estándar introdujo los tipos intptr_t
y uintptr_t
, que son tipos con y sin signo garantizados para poder mantener punteros:
uintptr_t p = (size_t) v;
Entonces, ¿cuál es la diferencia entre usar size_t
y uintptr_t
? Ambos no están firmados, y ambos deberían poder contener cualquier tipo de puntero, por lo que parecen funcionalmente idénticos. ¿Existe alguna razón real convincente para usar uintptr_t
(o mejor aún, a void *
) en lugar de una size_t
, aparte de la claridad? En una estructura opaca, donde el campo será manejado solo por funciones internas, ¿hay alguna razón para no hacerlo?
Del mismo modo, ptrdiff_t
ha sido un tipo con signo capaz de contener las diferencias de puntero y, por lo tanto, capaz de contener la mayoría de los punteros, entonces, ¿en qué se diferencia intptr_t
?
¿No están todos estos tipos básicamente sirviendo versiones trivialmente 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éntase libre de mencionarlos, ya que tengo la sospecha de que serán fundamentales para la respuesta "correcta".
size_t
y,uintptr_t
pero ¿qué pasa conptrdiff_t
yintptr_t
, no podrían ambos almacenar el mismo rango de valores en casi cualquier plataforma? ¿Por qué tener tipos enteros de tamaño de puntero con signo y sin signo, especialmente siptrdiff_t
ya tiene el propósito de un tipo de entero de tamaño de puntero con signo?