Стандарт C гарантує, що size_t
це тип, який може містити будь-який індекс масиву. Це означає, що, логічно, size_t
має бути можливість утримувати будь-який тип вказівника. Я читав на деяких сайтах, які з’ясував у Google, що це законно та / або завжди має працювати:
void *v = malloc(10);
size_t s = (size_t) v;
Тоді в C99 стандарт представив типи intptr_t
та uintptr_t
типи, які підписують та підписують типи, гарантовано вміщуючи покажчики:
uintptr_t p = (size_t) v;
Тож у чому різниця між використанням size_t
та uintptr_t
? Обидва не підписані, і обидва повинні мати можливість утримувати будь-який тип вказівника, тому вони здаються функціонально однаковими. Чи є якась реальна вагома причина використовувати uintptr_t
(а ще краще, а void *
), а не size_t
іншу, ніж ясність? Чи є в непрозорій структурі, де поле буде оброблятися лише внутрішніми функціями, чи немає цього?
Таким же чином, ptrdiff_t
був підписаний тип, здатний утримувати різницю покажчиків, а отже, здатний утримувати більшість будь-яких вказівників, тож чим його відрізняти intptr_t
?
Чи не всі ці типи в основному обслуговують тривіально різні версії однієї функції? Якщо ні, то чому? Що я не можу зробити з одним із них, що я не можу зробити з іншим? Якщо так, то чому C99 додав до мови два по суті зайвих типи?
Я готовий ігнорувати функціональні покажчики, оскільки вони не стосуються поточної проблеми, але сміливо їх згадую, оскільки у мене є підозрілі припущення, що вони будуть центральними у "правильній" відповіді.
size_t
і ,uintptr_t
крім того, що проptrdiff_t
таintptr_t
- з обидва з них буде мати можливість зберігати один і той же діапазон значень майже на будь-якій платформі? Чому цілі цілі підписані та непідписані вказівники розміру, особливо якщо вониptrdiff_t
вже призначені цілому цілому типу підписаного розміру.