size_t vs. uintptr_t

Standard C gwarantuje tosize_t to typ, który może pomieścić dowolny indeks tablicy. Oznacza to, że logiczniesize_t powinien być w stanie pomieścić dowolny typ wskaźnika. Przeczytałem na niektórych stronach, które znalazłem w Google, że jest to legalne i / lub powinno zawsze działać:

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

Tak więc w C99 standard wprowadziłintptr_t iuintptr_t typy, które są podpisane i typy niepodpisane gwarantują, że będą w stanie przechowywać wskaźniki:

uintptr_t p = (size_t) v;

Jaka jest różnica między używaniemsize_t iuintptr_t? Oba są niepodpisane i oba powinny mieć możliwość przechowywania dowolnego typu wskaźnika, więc wydają się funkcjonalnie identyczne. Czy istnieje jakikolwiek istotny powód, aby go użyćuintptr_t (lub jeszcze lepiej, avoid *) a niesize_t, inne niż jasność? W nieprzejrzystej strukturze, gdzie pole będzie obsługiwane tylko przez funkcje wewnętrzne, czy jest jakiś powód, aby tego nie robić?

A tym samym,ptrdiff_t był typem podpisanym zdolnym do utrzymywania różnic między wskaźnikami, a zatem zdolnym do trzymania większości wskaźników, więc jak się od nich różniintptr_t?

Czy wszystkie te typy nie obsługują zasadniczo różnych wersji tej samej funkcji? Jeśli nie, dlaczego? Co nie mogę zrobić z jednym z nich, którego nie mogę zrobić z innym? Jeśli tak, to dlaczego C99 dodał dwa zasadniczo zbędne typy do języka?

Jestem gotów zignorować wskaźniki funkcji, ponieważ nie dotyczą one bieżącego problemu, ale możesz je wspomnieć, ponieważ podejrzewam, że będą one kluczowe dla „poprawnej” odpowiedzi.

questionAnswers(7)

yourAnswerToTheQuestion