В нескольких примерах C ++ я вижу использование типа, в size_t
котором я бы использовал простой int
. Какая разница, и почему size_t
должно быть лучше?
В нескольких примерах C ++ я вижу использование типа, в size_t
котором я бы использовал простой int
. Какая разница, и почему size_t
должно быть лучше?
Ответы:
Заголовочные файлы stdlib.h и stddef.h определяют тип данных с именем size_t, который используется для представления размера объекта. Библиотечные функции, принимающие размеры, ожидают, что они будут иметь тип size_t, а оператор sizeof оценивается как size_t.
Фактический тип size_t зависит от платформы; Распространенной ошибкой является допущение, что size_t - это то же самое, что и unsigned int, что может привести к ошибкам в программировании, особенно когда 64-битные архитектуры становятся более распространенными.
Также проверьте, почему size_t имеет значение
/usr/include/stdlib.h
получает определение /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
и в нем по умолчанию используется значение, long unsigned int
если другой заголовочный файл не говорит иначе.
size_t - это тип, используемый для представления размеров (как следует из его имен). Его платформа (и даже потенциально реализация) зависима и должна использоваться только для этой цели. Очевидно, представляющий размер, size_t без знака. Многие функции stdlib, включая malloc, sizeof и различные функции строковых операций, используют size_t в качестве типа данных.
Int подписывается по умолчанию, и хотя его размер также зависит от платформы, он будет фиксированным 32 бита на большинстве современных компьютеров (и хотя size_t равен 64 битам в 64-битной архитектуре, int остается 32 битным в этих архитектурах).
Подводя итог: используйте size_t для представления размера объекта и int (или long) в других случаях.
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, чей режим памяти 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 в любом случае.
Это потому, что size_t может быть чем угодно, кроме int (может быть struct). Идея состоит в том, что он отделяет свою работу от базового типа.
size_t
указывается как целое число без знака . C11 §6.5.3.4 5 «Значение результата обоих операторов ( sizeof
_Alignof
) определяется реализацией, а его тип (целочисленный тип без знака) равен size_t
« ».
Определение 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;
SIZE_T
не то size_t
, о чем спрашивал ОП.
SIZE_T
полностью отличается от size_t
. Вы не можете объявить переменную типа SIZE_T
.