Size_t переносится?

GCC 4.4.1, C99

Я использую size_t, а size_t - это unsigned int. Однако это зависит от того, используете ли вы 32-разрядную или 64-разрядную версию.

Я буду использовать size_t для хранения размера буфера.

Поэтому я не думаю, что это было бы очень переносимым при использовании на разных архитектурах.

Просто вопрос, с использованием size_t на 32 или 64 битах. Какие ситуации могут вызвать самые серьезные проблемы?


person ant2009    schedule 08.11.2009    source источник


Ответы (7)


size_t гарантированно сможет хранить количество байтов любого объекта в вашей реализации. Вот почему тип возврата sizeof - size_t.

Так что да, он портативный.

person Bastien Léonard    schedule 08.11.2009
comment
size_t является переносимым, если вы не пытаетесь сохранять переменные типа size_t в двоичные файлы или отправлять их по сетевым соединениям. Как только вы начнете это делать, он станет таким же портативным, как очень непереносимая вещь, приклеенная к полу. - person ; 13.06.2012

Как говорили другие, size_t является правильным и совершенно приемлемым для хранения результата sizeof() или размера любого представимого объекта в байтах. Вам следует остерегаться следующего:

  1. size_t имеет тот же размер, что и целочисленный тип без знака. Это не обязательно то же количество байтов, что и у самого большого целочисленного типа без знака, unsigned int, unsigned long и т. Д.
  2. sizeof(size_t) - это количество байтов, определяемое реализацией, поэтому memcpy 'его или присвоение любому целочисленному типу, отличному от uintmax_t, - плохая идея. Я даже не уверен, что можно с уверенностью предположить, что он такого же размера или меньше, чем uintmax_t.
  3. Запись значения size_t в двоичный файл и чтение его обратно в size_t другим процессом, на другой машине или чем-то, скомпилированным с другими параметрами компилятора, может быть опасно для вашего здоровья.
  4. Отправлять значение size_t по сети и пытаться получить его с помощью sizeof(size_t) буфера на другой стороне довольно небезопасно.

Все это стандартные проблемы с любым другим целочисленным типом, кроме unsigned char. Таким образом, size_t столь же переносим, ​​как и любой другой целочисленный тип.

person D.Shawley    schedule 08.11.2009

Имеет смысл использовать size_t или ssize_t для буфера, если вы используете malloc () или read (). Для переносимости используйте SIZE_MAX, SSIZE_MAX, sizeof (type-in-your-buffer) и% zd или% zu printf ().

person paul    schedule 08.11.2009
comment
К сожалению, компилятор Microsoft C не поддерживает модификатор размера z для printf(). - person Phil Miller; 08.11.2009
comment
Модификатор z является частью стандарта C99. Компиляторы Microsoft до сих пор использовали C89 / 90. В C89 / 90 возможность size_t печати должна быть реализована вручную. - person AnT; 08.11.2009
comment
Эти бас ..., я забыл. Ну, он действительно спросил о C99. Я предполагаю, что он действительно спросил о самой серьезной проблеме, которая может быть либо оптимистичным распределением Linux, либо беспечным предположением, что (count * sizeof ()) не переполняется, или, возможно, думая, что вам нужно выделить столько памяти в первую очередь. - person paul; 08.11.2009
comment
Microsoft поддерживает модификатор длины z начиная с Visual Studio 2015. Поддерживаются несколько других модификаторов длины. См. Раздел <stdio.h> and <conio.h> в Функции, исправления и критические изменения среды выполнения C (CRT) в Visual Studio 14 CTP1 - person MikeOnline; 28.08.2018

У вас также есть off_t и ptrdiff_t / ssize_t, которые одинаково различаются в зависимости от архитектуры.

Если вы используете их правильно, они переносимы для разных архитектур. В 32-битной системе все они будут иметь ширину 32 бита, а в 64-битной системе все они будут иметь ширину 64 бита. Это то, что вам нужно - размер буфера не может быть больше 32-битного size_t в 32-битной системе, но он может быть намного больше в 64-битной системе.

Вы никогда не должны использовать целые числа, длинные числа или что-то еще. Помимо всего прочего, размер long зависит от платформы (32-битный в большинстве 32-битных систем, 64-битный в 64-битных системах Unix, 32-битный в 64-битной Windows).

person BlackAura    schedule 08.11.2009

Трудно понять, что вы подразумеваете под портативным в данном случае. Термин «переносимый» допускает множество различных интерпретаций.

size_t имеет очень конкретную цель. Он может содержать размер любого объекта в данной реализации. Т.е. это тип, который всегда может получить результат оператора sizeof. size_t не имеет другой цели, и в рамках предполагаемого применения он на 100% переносим, ​​настолько же переносим, ​​насколько это возможно.

О каком портативном устройстве вы спрашиваете, опять же, не ясно.

person AnT    schedule 08.11.2009
comment
Я использую size_t, чтобы получить размер буфера. Я делаю сообщения с программированием сокетов, и исходный код будет скомпилирован как для Linux, так и для Windows. Мне нужно будет получить size_t данных, которые были отправлены от клиента. Спасибо - person ant2009; 08.11.2009
comment
@robUK, вы должны добавить эту важную информацию к своему вопросу. - person quinmars; 09.11.2009

Зависит от того, для чего вы используете size_t.

Если вы используете его для определения размера буфера памяти, это будет безопасно, поскольку size_t достаточно велик, чтобы адресовать всю память любого компьютера. Так что, если буфер памяти больше, у вас все равно есть проблема.

С другой стороны, если вы используете его как общее беззнаковое целое число, например, для подсчета количества звезд во Вселенной, у вас может возникнуть проблема в 32-битной системе (не уверен в 64-битных системах).

person Jonatan    schedule 08.11.2009
comment
Не правда. size_t достаточно, чтобы удерживать размер самого большого объекта, поддерживаемого реализацией. size_t НЕ достаточно велик, чтобы адресовать всю память. Для последнего вам понадобится _3 _ / _ 4_. - person AnT; 08.11.2009
comment
Я исправился. Но все же самый крупный объект - это то, что вам, вероятно, в этом случае нужно, иначе у вас возникнет другая проблема. - person Jonatan; 08.11.2009

Единственная серьезная проблема с этим - это попытка получить доступ к довольно большому массиву или большому числу size_t.

Точно так же, как обычного int может быть достаточно в 64-битной системе, но он может вызвать сбой в 32-битной системе, потому что он слишком велик для int в 32-битной системе.

person alternative    schedule 08.11.2009