O padrão C garante que esse size_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. Li em alguns sites que achei no Google que isso é legal e / ou sempre deve funcionar:
void *v = malloc(10);
size_t s = (size_t) v;
Então, em C99, o padrão introduziu os tipos intptr_t
e uintptr_t
, que são assinados e não assinados, com a garantia de poder conter ponteiros:
uintptr_t p = (size_t) v;
Então, qual é a diferença entre usar size_t
e uintptr_t
? Ambos não são assinados e devem poder manter qualquer tipo de ponteiro, para que pareçam funcionalmente idênticos. Existe alguma razão real e convincente para usar uintptr_t
(ou melhor ainda, a void *
) ao invés de a size_t
, além da clareza? Em uma estrutura opaca, onde o campo será tratado apenas por funções internas, existe alguma razão para não fazer isso?
Da mesma forma, ptrdiff_t
foi um tipo assinado capaz de conter diferenças de ponteiro e, portanto, capaz de conter quase todo o ponteiro, então como é diferente intptr_t
?
Todos esses tipos não servem basicamente versões trivialmente diferentes da mesma função? Se não, por que? O que não posso fazer com um deles que não posso fazer com outro? Se sim, por que o C99 adicionou dois tipos essencialmente supérfluos ao idioma?
Estou disposto a ignorar os ponteiros de função, pois eles não se aplicam ao problema atual, mas fique à vontade para mencioná-los, pois tenho uma suspeita de que eles serão essenciais para a resposta "correta".
size_t
e,uintptr_t
masptrdiff_t
e quanto aintptr_t
- eles não seriam capazes de armazenar o mesmo intervalo de valores em quase qualquer plataforma? Por que os tipos de números inteiros do tamanho de um ponteiro assinados e não assinados, principalmente septrdiff_t
já servem ao propósito de um tipo inteiro do tamanho de um ponteiro assinado