Тема: Різниця між uinptr_t, size_t, ptrdiff_t
У чому різниця між uinptr_t, size_t, ptrdiff_t?
Я от прочитав, що тип size_t - це беззнаковий тип і що в нього можна помістити вказівник, але навіщо тоді є тип uinptr_t?
Яка тоді між ними різниця?
Ви не увійшли. Будь ласка, увійдіть або зареєструйтесь.
Ласкаво просимо вас на україномовний форум з програмування, веб-дизайну, SEO та всього пов'язаного з інтернетом та комп'ютерами.
Будемо вдячні, якщо ви поділитись посиланням на Replace.org.ua на інших ресурсах.
Для того щоб створювати теми та надсилати повідомлення вам потрібно Зареєструватись.
Український форум програмістів → C++ → Різниця між uinptr_t, size_t, ptrdiff_t
Сторінки 1
Для відправлення відповіді ви повинні увійти або зареєструватися
У чому різниця між uinptr_t, size_t, ptrdiff_t?
Я от прочитав, що тип size_t - це беззнаковий тип і що в нього можна помістити вказівник, але навіщо тоді є тип uinptr_t?
Яка тоді між ними різниця?
size_t - це беззнаковий тип і що в нього можна помістити вказівник
А чи завжди можна? Якщо, наприклад, використовується модель пам'яті, де вказівник задається як сегмент і зміщення, а розмір об'єкта не може перевищувати максимального розміру сегмента, тоді size_t мав би відповідати розрядності зміщення (без сегмента), і помістити вказівник у нього, в загальному випадку, було б неможливо.
Це для екзотичних архітектур.
Читаємо стандарт:
The following type designates a signed integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
uintptr_t
ptrdiff_t
which is the signed integer type of the result of subtracting two pointers;
size_t
which is the unsigned integer type of the result of the sizeof operator
Для 32-х і 64-бітних x86 та ARM, наскільки я розумію, різниці дійсно немає. Але це не єдині можливі моделі пам'яті. Скажімо, 16-бітні 8086 мали максимальний розмір об'єктів у 65536 байтів, але "далекі" вказівники (FAR) були удвічі більшими, 32 біти (вони розкладалися у два різні регістри, причому вони не просто додавалися, а із зсувом, так що вся пам'ять мала об'єм до 1МБ). Тобто size_t мав бути unsigned short, але uintptr_t вже unsigned long.
Тобто це таки різні штуки?
І для вказівників краще використовувати uinptr_t
Для вказівників краще використовувати вказівники.
Я от прочитав, що тип size_t - це беззнаковий тип і що в нього можна помістити вказівник
[...]
Тобто це таки різні штуки?
Тип uintptr_t - це і є тип, спеціально призначений для "зберігання" вказівників. Саме в цей тип (а не в size_t) можна безпечно записати вказівник. Для того цей тип і був введений.
Тип size_t - беззнаковий тип, здатний зберігати байтовий розмір найбільшого безперервного об'єкта. Однак з цього ніяк не випливає, що "в змінну типу size_t може бути безпечно поміщений вказівник." Ніхто вам не пообіцяє, що реалізація дозволить вам створювати об'єкти розміром "на всю пам'ять" (на весь адресний простір). Реалізація має право обмежити максимальний розмір об'єкта на свій розсуд і, відповідно, зменшити розмір типу size_t. З цієї причини в тип size_t не можна записати вказівник. Розмір типу size_t в загальному випадку - менше або дорівнює розміру вказівника.
Класичний приклад реалізацій з "маленьким" size_t - платформи з сегментною організацією пам'яті. Твердження, що в тип size_t завжди можна записати вказівник (як за посиланням), як правило робляться через незнання людьми, які не бачили ніяких інших моделей пам'яті, крім плоскої. Не намагайтеся використовувати тип size_t для зберігання вказівників. Для цього існує uintptr_t.
Тип ptrdiff_t - знаковий тип, який призначений для зберігання різниці двох вказівників, що вказують на елементи одного і того ж масиву. З цього випливає, що в загальному випадку тип ptrdiff_t повинен бути на 1 біт ширше, ніж тип size_t. Однак специфікація С++ не вимагає цього і дозволяють типу ptrdiff_t мати ту ж саму ширину, що size_t. Це означає, що якщо ви зумієте створити масив, розміром більше ніж SIZE_MAX / 2, то різниця між покажчиками на елементи такого масиву запросто може не поміститися в ptrdiff_t. Деякі реалізації, в яких ptrdiff_t і size_t мають однакову ширину, просто забороняють створювати об'єкти, розміром більше SIZE_MAX / 2 байт. А деякі - не забороняють і перекладають всю відповідальність на плечі користувача.
Сторінки 1
Для відправлення відповіді ви повинні увійти або зареєструватися