Відповіді:
size_t
Тип є цілим числом без знака тип , який є результатом sizeof
оператора (і offsetof
оператора), тому він гарантовано буде досить великим , щоб утримувати розмір найбільшого об'єкту система може обробляти (наприклад, статичний масив 8Gb).
size_t
Типу може бути більше, дорівнює або менше , ніж unsigned int
, і компілятор може робити припущення про це для оптимізації.
Більш точну інформацію ви можете знайти в стандарті C99, розділ 7.17, проект якого доступний в Інтернеті у форматі pdf , або в стандарті C11, розділ 7.19, також доступний у вигляді проекту PDF .
size_t
може представляти! Якщо це не так, хто робить?
Класичний С (ранній діалект С, описаний Брайаном Керніган і Деннісом Річі в "Мові програмування на C", Prentice-Hall, 1978) не передбачав size_t
. Комітет зі стандартів C запроваджено size_t
для усунення проблеми переносимості
Докладно пояснено на embedded.com (з дуже хорошим прикладом)
Коротше кажучи, size_t
це ніколи не є негативним, і це забезпечує максимальну ефективність, тому що це typedef'd - це цілий цільовий неподписаний тип, який є достатньо великим, але не надто великим - для розміру найбільшого можливого об'єкта на цільовій платформі.
Розміри ніколи не повинні бути негативними, і справді size_t
це непідписаний тип. Крім того, оскільки size_t
це не підписано, ви можете зберігати числа, приблизно вдвічі більші, ніж у відповідному підписаному типі, тому що ми можемо використовувати біт знака для представлення величини, як і всі інші біти в цілому цілі, що не підписується. Коли ми отримуємо ще один біт, ми множимо діапазон чисел, який ми можемо представляти, на коефіцієнт приблизно два.
Отже, ви запитаєте, чому б просто не використовувати unsigned int
? Він може не мати достатньо великої кількості. У реалізації, де unsigned int
32 біти, найбільша кількість вона може представляти 4294967295
. Деякі процесори, такі як IP16L32, можуть копіювати об'єкти розміром більше 4294967295
байтів.
Отже, запитаєте ви, чому б не використати unsigned long int
? Це вимагає плати за продуктивність на деяких платформах. Стандарт C вимагає, щоб він long
займав принаймні 32 біти. Платформа IP16L32 реалізує кожну 32-бітну довжину як пару 16-бітних слів. Практично всі 32-розрядні оператори на цих платформах вимагають двох інструкцій, якщо не більше, тому що вони працюють з 32 бітами в двох 16-бітових фрагментах. Наприклад, для переміщення по 32-бітовій довжині зазвичай потрібні дві інструкції на машині - одна для переміщення кожного 16-бітного куска.
Використання size_t
дозволяє уникнути цієї плати за продуктивність. Згідно з цією фантастичною статтею , "Тип size_t
- це typedef, який є псевдонімом певного цілого цілого числа без підпису, як правило, unsigned int
або unsigned long
, можливо, навіть unsigned long long
. Кожна реалізація Standard C повинна вибирати ціле цільове число без підпису, але не більше, ніж потрібно-- представляти розмір найбільшого можливого об'єкта на цільовій платформі. "
unsigned int
і коливається, залежить від однієї системи до іншої. Потрібно, щонайменше 65536
, але в деяких системах це 4294967295
може бути 18446744073709551615
(2 ** 64-1).
unsigned char
). Здається, стандарт ніде не містить рядка "65535" або "65536", а "+32767" зустрічається лише (1,9: 9) у примітці як можливе найбільше ціле число, яке може бути представлене в int
; не дається гарантія навіть того, що INT_MAX
не може бути меншим за це!
Тип size_t - це тип, що повертається оператором sizeof. Це ціле число без підпису, здатне виражати розмір у байтах будь-якого діапазону пам'яті, підтримуваного на хост-машині. Це (як правило) пов'язано з ptrdiff_t тим, що ptrdiff_t - це ціле цільове значення, яке підписується таким чином, що sizeof (ptrdiff_t) і sizeof (size_t) рівні.
При написанні коду C ви завжди повинні використовувати size_t, коли маєте справу з діапазонами пам'яті.
З іншого боку, тип int визначається як розмір цілого (підписаного) цілого значення, який хост-машина може використовувати для найбільш ефективного виконання арифметики цілочисленних чисел. Наприклад, на багатьох старих комп'ютерах типу ПК значення sizeof (size_t) було б 4 (байт), але sizeof (int) було б 2 (байт). 16-бітна арифметика була швидшою, ніж 32-бітна арифметика, хоча процесор міг обробляти (логічний) простір пам'яті до 4 Гб.
Використовуйте тип int лише тоді, коли ви дбаєте про ефективність, оскільки його фактична точність сильно залежить як від параметрів компілятора, так і від архітектури машини. Зокрема, стандарт C визначає такі інваріанти: sizeof (char) <= sizeof (короткий) <= sizeof (int) <= sizeof (довгий), не встановлюючи інших обмежень щодо фактичного подання точності, доступної програмісту для кожного з ці примітивні типи.
Примітка. Це НЕ те саме, що в Java (що фактично визначає бітову точність для кожного з типів "char", "byte", "short", "int" і "long").
size_t
Здатний представляти розмір будь-якого окремого об'єкта (наприклад, число, масив, структура). Весь діапазон пам’яті може перевищуватиsize_t
size_t
- я сподіваюся, ви цього не маєте на увазі. Здебільшого ми не маємо справи з масивами, де важливість навіть простоти адресного простору та портативності. У цих випадках ви приймете size_t
. У кожному іншому випадку ви приймаєте індекси з (підписаних) цілих чисел. Тому що плутанина (що настає без попередження), що виникає через несподівану поведінку під підписом неподписаних, зустрічається частіше і гірше, ніж проблеми переносимості, які можуть виникнути в інших випадках.
Тип size_t повинен бути достатньо великим, щоб зберігати розмір будь-якого можливого об’єкта. Непідписаний int не повинен задовольняти цій умові.
Наприклад, у 64-бітових системах int та unsigned int можуть бути шириною 32 біти, але size_t повинен бути достатньо великим, щоб зберігати номери більше 4G
size_t
це було б таким великим, лише якщо компілятор міг прийняти тип X такий, що sizeof (X) дасть значення, що перевищує 4G. Більшість компіляторів відмовляться, наприклад typedef unsigned char foo[1000000000000LL][1000000000000LL]
, і навіть foo[65536][65536];
можуть бути законно відхилені, якби це перевищувало встановлений документально визначений ліміт.
Цей уривок з посібника glibc 0.02 також може бути актуальним при дослідженні теми:
Існує потенційна проблема з типом size_t та версіями GCC до випуску 2.4. ANSI C вимагає, щоб size_t завжди був непідписаним типом. Для сумісності з файлами заголовків існуючих систем GCC визначає size_t в stddef.h' to be whatever type the system's
sys / types.h 'визначає його як. Більшість систем Unix, які визначають size_t в `sys / types.h ', визначають його як підписаний тип. Деякий код у бібліотеці залежить від того, що size_t є непідписаним типом, і він не працюватиме правильно, якщо він підписаний.
Код бібліотеки GNU C, який очікує непідписання size_t, є правильним. Визначення size_t як підписаного типу є невірним. Ми плануємо, що у версії 2.4 GCC завжди визначатиме size_t як fixincludes' script will massage the system's
неподписаний тип, а sys / types.h ', щоб не суперечити цьому.
Тим часом ми вирішуємо цю проблему, кажучи явно GCC використовувати неподписаний тип size_t при компіляції бібліотеки GNU C. `configure 'автоматично визначить, який тип GCC використовує для size_t домовитись, щоб змінити його, якщо це необхідно.
Якщо мій компілятор встановлений на 32 біт, size_t
це не що інше, як typedef для unsigned int
. Якщо мій компілятор встановлений на 64 біт, size_t
це не що інше, як typedef для unsigned long long
.
unsigned long
для обох випадків на деяких ОС.
size_t - розмір вказівника.
Отже, в 32 бітах або загальній моделі ILP32 (ціла, довга, покажчик) модель size_t становить 32 біта. а в 64 бітах або загальна модель LP64 (довга, вказівна) size_t становить 64 біта (цілі числа все ще 32 біти).
Є й інші моделі, але це ті, які використовують g ++ (принаймні, за замовчуванням)
size_t
не обов'язково має той же розмір, що і вказівник, хоча це зазвичай. Вказівник повинен бути в змозі вказувати на будь-яке місце в пам'яті; size_t
лише має бути достатньо великим, щоб відображати розміри найбільшого одного об'єкта.