Яка різниця між size_t та int в C ++?


173

У кількох прикладах C ++ я бачу використання типу, size_tде я б використав простий int. У чому різниця, і чому size_tслід краще?


3
Для фактичного прикладу, коли вони не взаємозамінні, дивіться питання, яке я задавав раніше: stackoverflow.com/questions/645168/…
Тайлер Макенрі

Відповіді:


153

З дружньої Вікіпедії :

Файли заголовків stdlib.h та stddef.h визначають тип даних під назвою size_t, який використовується для представлення розміру об'єкта. Функції бібліотеки, які приймають розміри, очікують, що вони будуть типу size_t, а оператор sizeof оцінює до size_t.

Фактичний тип size_t залежить від платформи; Поширена помилка полягає в тому, що вважати, що size_t є тим самим, що і непідписаний int, що може призвести до помилок програмування, особливо, коли 64-бітні архітектури стають більш поширеними.

Також перевірте, чому розмір має значення


76
І так, що таке size_t?
NDEthos

8
@NDEthos Це залежить! На цьому тут Linux /usr/include/stdlib.hотримує визначення, /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.hа в ньому - за замовчуванням, long unsigned intякщо інший файл заголовка не говорить інше.
Девід Тонхофер

1
Я підтверджую, що налаштування size_t to int є небезпечним . Це може бути поза темою, але як написати патч самостійно, щоб виправити такі помилки, коли він трапляється тисячі разів у ядрі Linux?
користувач2284570

36

size_t - тип, який використовується для представлення розмірів (як випливає з його назв). Його платформа (і навіть потенційно реалізація) залежить, і її слід використовувати лише для цієї мети. Очевидно, що представляє розмір, розмір_t не підписаний. Багато функцій stdlib, включаючи malloc, sizeof та різні функції рядкових операцій, використовують size_t як тип даних.

Int підписаний за замовчуванням, і хоча його розмір також залежить від платформи, він буде фіксованим 32-бітним на більшості сучасних машин (і хоча size_t становить 64 біти в 64-бітній архітектурі, int залишається 32-бітним в цих архітектурах).

Підводячи підсумок: використовуйте size_t для представлення розміру об'єкта, а int (або довгий) в інших випадках.


12

size_tТип визначається як беззнаковое інтегрального типу sizeofоператора. У реальному світі ви часто будете intвизначатись як 32 біти (для зворотної сумісності), але size_tвизначені як 64 біти (тому ви можете оголошувати масиви та структури розміром більше 4 Гб) на 64-бітних платформах. Якщо a long intтакож є 64-бітним, це називається конвенцією LP64; якщо long intце 32 біти, але long long intвказівники - 64 біти, це LLP64. Ви також можете отримати зворотну програму, яка використовує 64-бітні інструкції для швидкості, але 32-бітні вказівники для економії пам’яті. Також intпідписаний іsize_t не підписаний.

Історично існувало ряд інших платформ, де адреси були ширшими або короткішими, ніж їх розмір int. Насправді, у 70-ті та на початку 80-х це було більше, ніж ні: усі популярні 8-бітні мікрокомп'ютери мали 8-бітні регістри та 16-бітні адреси, а перехід між 16 та 32 бітами також дав багато машин, які мали адреси ширші, ніж їхні регістри. Я час від часу все ще бачу запитання щодо Borland Turbo C для MS-DOS, у режимі якого величезна пам'ять було 20-бітові адреси, збережені в 32 бітах на 16-бітному процесорі (але які могли підтримувати 32-бітний набір інструкцій 80386); Motorola 68000 мав 16-бітний ALU з 32-бітовими регістрами та адресами; були мейнфрейми IBM з 15-бітними, 24-бітними або 31-бітовими адресами. Ви також все ще бачите різні розміри ALU та шини адрес у вбудованих системах.

Будь-який час intменший, ніж size_tви намагаєтесь зберегти розмір або зсув дуже великого файлу чи об'єкта в unsigned int, є ймовірність, що він може переповнюватись і викликати помилку. З аint , також існує можливість отримання від’ємного числа. Якщо intабо unsigned intширше, програма запуститься правильно, але не втрачає пам'ять.

Як правило, ви повинні використовувати правильний тип для цієї мети, якщо ви хочете переносити їх. Багато людей порекомендують використовувати підписану математику замість непідписаної (щоб уникнути неприємних, тонких помилок, як-от 1U < -3). Для цього стандартна бібліотека визначаєptrdiff_t в <stddef.h>якості знакового типу результату віднімання покажчика з інших.

З цього приводу можливе вирішення меж - перевірити всі адреси та компенсації проти INT_MAXабо будь-якого 0або, INT_MINякщо це доречно, та включити попередження компілятора про порівняння підписаних та неподписаних кількостей у випадку, якщо ви пропустите будь-яку. Ви в будь-якому випадку завжди повинні завжди перевіряти доступ до масиву на переповнення в C.


8

Це тому, що size_t може бути будь-яким іншим, ніж int (можливо, структура). Ідея полягає в тому, що вона відокремлює роботу від основного типу.


8
Я думаю, що size_t насправді гарантовано є псевдонімом для непідписаного цілого числа, тому це не може бути структурою. Я зараз не маю довідки, яка б це підтвердила.
розмотайте

9
@unwind: C99: TC3, 7.17 §2
Крістоф

1
@danio Чому так? Ви можете пояснити?
Гриф Рюппелла

2
Я б не посилався на cplusplus, якби я був ти! Якщо ви не можете процитувати главу, вірш, абзац і рядок, тоді це все просто з чужих слів! :-)
graham.reeds

1
size_tзадається як непідписаний цілочисельний тип. C11 §6.5.3.4 5 "Значення результату обох операторів ( sizeof _Alignof) визначено реалізацією, а його тип (непідписаний цілочисельний тип) - size_t".
chux

-1

Визначення SIZE_Tнаведено на веб - сторінці : https://msdn.microsoft.com/en-us/library/cc441980.aspx та https://msdn.microsoft.com/en-us/library/cc230394.aspx

Вставте тут необхідну інформацію:

SIZE_Tявляє собою ULONG_PTRмаксимальну кількість байтів, на які може вказувати вказівник.

Цей тип декларується наступним чином:

typedef ULONG_PTR SIZE_T;

A ULONG_PTR- це ненаписаний довгий тип, який використовується для точності вказівника. Він використовується під час наведення покажчика на довгий тип для виконання арифметики вказівника.

Цей тип декларується наступним чином:

typedef unsigned __int3264 ULONG_PTR;

2
SIZE_Tне size_tте, про що запитувала ОП.
ikegami

2
Це розширення Microsoft, а не частина стандартної мови.
Девіслор

SIZE_Tабсолютно відрізняється від size_t. Ви не можете оголосити змінну типу SIZE_T.
калорійність
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.