В чем разница между size_t и int в C ++?

173

В нескольких примерах C ++ я вижу использование типа, в size_tкотором я бы использовал простой int. Какая разница, и почему size_tдолжно быть лучше?

tunnuz
источник
3
Для реального примера, где они не являются взаимозаменяемыми, см. Вопрос, который я задавал ранее: stackoverflow.com/questions/645168/…
Тайлер МакГенри

Ответы:

153

Из дружественной Википедии :

Заголовочные файлы stdlib.h и stddef.h определяют тип данных с именем size_t, который используется для представления размера объекта. Библиотечные функции, принимающие размеры, ожидают, что они будут иметь тип size_t, а оператор sizeof оценивается как size_t.

Фактический тип size_t зависит от платформы; Распространенной ошибкой является допущение, что size_t - это то же самое, что и unsigned int, что может привести к ошибкам в программировании, особенно когда 64-битные архитектуры становятся более распространенными.

Также проверьте, почему size_t имеет значение

Жоао да Силва
источник
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 для интонации опасен . Это может быть не по теме, но как написать патч в одиночку, чтобы исправить ошибки такого рода, когда они происходят тысячи раз в ядре Linux?
user2284570
36

size_t - это тип, используемый для представления размеров (как следует из его имен). Его платформа (и даже потенциально реализация) зависима и должна использоваться только для этой цели. Очевидно, представляющий размер, size_t без знака. Многие функции stdlib, включая malloc, sizeof и различные функции строковых операций, используют size_t в качестве типа данных.

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

Подводя итог: используйте size_t для представления размера объекта и int (или long) в других случаях.

Аксель Циглер
источник
12

size_tТип определяется как беззнаковое интегрального типа sizeofоператора. В реальном мире вы часто будете видеть int32 size_t-битные (для обратной совместимости), но 64-битные (чтобы вы могли объявлять массивы и структуры размером более 4 ГиБ) на 64-битных платформах. Если a long intтакже 64-битный, это называется соглашением LP64; Если long int32- long long intбитный, а указатели 64-битные, это LLP64. Вы также можете получить обратную, программу, которая использует 64-битные инструкции для скорости, но 32-битные указатели для экономии памяти. Также intподписано и size_tне подписано.

Исторически было много других платформ, где адреса были шире или короче, чем собственный размер int. Фактически, в 70-х и в начале 80-х это было более распространенным, чем нет: все популярные 8-битные микрокомпьютеры имели 8-битные регистры и 16-битные адреса, а переход между 16 и 32-битными также породил множество машин, которые адреса были шире, чем их регистры. Иногда я все еще вижу здесь вопросы о Borland Turbo C для MS-DOS, чей режим памяти Huge содержал 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 в любом случае.

Davislor
источник
8

Это потому, что size_t может быть чем угодно, кроме int (может быть struct). Идея состоит в том, что он отделяет свою работу от базового типа.

graham.reeds
источник
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.
Calocedrus