Standard C gwarantuje, że size_t
jest to typ, który może przechowywać dowolny indeks tablicy. Oznacza to, że logicznie size_t
powinno być w stanie pomieścić dowolny typ wskaźnika. Czytałem na niektórych stronach, które znalazłem w Googles, że jest to legalne i / lub powinno zawsze działać:
void *v = malloc(10);
size_t s = (size_t) v;
Zatem w C99 standard wprowadził typy intptr_t
i uintptr_t
, które są podpisane, a typy niepodpisane gwarantują, że będą mogły przechowywać wskaźniki:
uintptr_t p = (size_t) v;
Jaka jest różnica między używaniem size_t
a uintptr_t
? Oba są niepodpisane i oba powinny być w stanie pomieścić dowolny typ wskaźnika, więc wydają się funkcjonalnie identyczne. Czy istnieje jakiś naprawdę ważny powód, aby używać uintptr_t
(lub jeszcze lepiej: a void *
) zamiast a size_t
, innego niż jasność? Czy w nieprzejrzystej strukturze, w której pole będzie obsługiwane tylko przez funkcje wewnętrzne, czy jest jakiś powód, aby tego nie robić?
Z tego samego powodu, ptrdiff_t
czy był typem podpisanym zdolnym do utrzymywania różnic kursorów, a zatem zdolnym do utrzymywania większości wskaźników, więc czym się różni intptr_t
?
Czy wszystkie te typy nie służą w zasadzie trywialnie różnym wersjom tej samej funkcji? Jeśli nie to dlaczego? Co nie mogę zrobić z jednym z nich, czego 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 obecnego problemu, ale śmiało mogę o nich wspomnieć, ponieważ mam podejrzenia, że będą kluczowe dla „poprawnej” odpowiedzi.
size_t
auintptr_t
ale coptrdiff_t
iintptr_t
- nie oba z nich będzie w stanie przechowywać ten sam zakres wartości niemal na każdej platformie? Dlaczego mamy zarówno podpisane, jak i niepodpisane typy liczb całkowitych wielkości wskaźnika, szczególnie jeśliptrdiff_t
już służą celowi podpisanego typu liczby całkowitej.