size_t vs. uintptr_t

O padrão C garante quesize_t é um tipo que pode conter qualquer índice de matriz. Isso significa que, logicamente,size_t deve ser capaz de manter qualquer tipo de ponteiro. Eu li em alguns sites que eu encontrei nos Googles que isso é legal e / ou deve sempre funcionar:

void *v = malloc(10);
size_t s = (size_t) v;

Então, em C99, o padrão introduziu ointptr_t euintptr_t tipos, que são tipos assinados e não assinados garantidos para manter ponteiros:

uintptr_t p = (size_t) v;

Então, qual é a diferença entre usarsize_t euintptr_t? Ambos são sem sinal, e ambos devem ser capazes de manter qualquer tipo de ponteiro, então eles parecem funcionalmente idênticos. Existe algum motivo real para usaruintptr_t (ou melhor ainda, umvoid *) ao invés de umsize_t, além de clareza? Em uma estrutura opaca, onde o campo será tratado apenas por funções internas, existe alguma razão para não fazer isso?

Pela mesma razão,ptrdiff_t tem sido um tipo assinado capaz de manter as diferenças de ponteiro, e, portanto, capaz de segurar mais qualquer ponteiro, assim como é distinto deintptr_t?

Não são todos esses tipos basicamente servindo versões trivialmente diferentes da mesma função? Se não, por quê? O que não posso fazer com um deles que não posso fazer com o outro? Em caso afirmativo, por que C99 adicionou dois tipos essencialmente supérfluos ao idioma?

Estou disposto a desconsiderar indicadores de função, pois eles não se aplicam ao problema atual, mas sinta-se à vontade para mencioná-los, pois tenho uma suspeita de que eles estarão no centro da resposta "correta".

questionAnswers(7)

yourAnswerToTheQuestion