2009-10-08 2 views
7

При ответе на комментарий к другому моему ответу here, я нашел то, что думаю может быть отверстием в стандарте C (c1x, я не проверял ранее и да, я знаю, что невероятно маловероятно, что я один среди всех жителей планеты обнаружил ошибку в стандарте). Ниже следует информация:Потенциальная проблема с C стандартными символами malloc'ing

  1. Раздел 6.5.3.4 («Оператор размера»), пункт 2, устанавливает "The sizeof operator yields the size (in bytes) of its operand".
  2. В параграфе 3 этого раздела говорится: "When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1".
  3. Раздел 7.20.3.3 описывает void *malloc(size_t sz), но все, что он говорит, это "The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate". В нем нет никаких упоминаний о том, какие единицы используются для аргументации.
  4. Приложение E запускает 8: минимальное значение значение для CHAR_BIT, поэтому символы могут быть более одного байта в длину.

Мой вопрос просто:

В среде, где символ имеет ширину 16 бит, будет malloc(10 * sizeof(char)) выделить 10 символов (20 байт) или 10 байтов? Точка 1 выше, по-видимому, указывает на первую, точка 2 указывает на последнюю.

У кого-нибудь, у кого больше C-standard-fu, чем у меня есть ответ на этот вопрос?

ответ

16

В 16-битной среде charmalloc(10 * sizeof(char)) выделит 10 char с (10 байт), потому что если char составляет 16 бит, то, что архитектура/реализация определяет байт, как 16 бит. A char не является октетом, это байт. На старых компьютерах это может быть больше, чем 8 бит de-facto, который у нас есть сегодня.

Соответствующий раздел из стандарта C следующим образом:

3.6 Термины, определения и символы

байт - адресуемой единицей хранения данных достаточно большой, чтобы держать любого члена основного набора исполнения окружающая среда ...

ПРИМЕЧАНИЕ 2 - Байт состоит из непрерывной последовательности бит, число которой определяется реализацией.

+1

На самом деле, я думаю, вы можете иметь его там. основанный на вашем ответе, я нашел 3.6 (в «Терминах, определениях и символах»), указав «байтовый адресный блок хранения данных, достаточно большой, чтобы удерживать любого члена базового набора символов среды выполнения ... ПРИМЕЧАНИЕ 2 - Байт состоит из непрерывной последовательности бит, число которой определяется реализацией ». – paxdiablo

+0

Черт, подумайте о славе и похвалах, которые я получил бы за то, что нашел проблему в стандарте. Хорошо, вернемся к работе :-) – paxdiablo

+0

Еще раз, я нахожу себе повторение «Я должен получить копию стандарта» мантры. Я добавлю вашу стандартную цитату к моему ответу за полноту. –

1

Не являются ли единицы измерения размера «size_t sz» в каком-либо адресном устройстве вашей архитектуры? Я работаю с DSP, адреса которого соответствуют 32-битным значениям, а не байтам. malloc (1) получает указатель на 4-байтовую область.

+1

С точки зрения формулировки в стандарте C «байт» на этой архитектуре составляет 32 бита. Немного запутанная вещь - то, что стандарт C называет «байтом», не обязательно соответствует (сегодняшнему) общему использованию слова. – caf

+1

И по той же причине, когда сетевые стандарты означают «8 бит», они говорят «октет», а не «байт». Только в розничных контекстах байт имеет однозначно 8 бит, как в «МБ полосы пропускания», «ГБ ОЗУ», «ТБ дискового пространства». –

+0

А, это имеет смысл. Наверное, мы придерживаемся двусмысленности для не-языковых юристов, поскольку такие слова, как «мегаоценты» или «кибиотекты», не очень эффективны. – twon33

2

В стандарте C99 строгая корреляция между байтами, char и размер объекта приведен в 6.2.6.1/4 «Представления типов - Общие»:

Значения хранятся в объектах небитового поля любого другого типа объекта состоят из n × CHAR_BIT бит, где n - размер объекта этого типа, в байтах. Значение может быть скопировано в объект типа unsigned char [n] (например, memcpy); результирующий набор байтов называется представлением объекта значения.

В стандарте С ++ такое же соотношение приведено в 3.9/2 «типов»:

Для любого объекта (кроме базового класса подобъекта) типа СТРУЧКА T, является ли или нет объект имеет допустимое значение типа T, базовые байты (1.7), составляющие объект, могут быть скопированы в массив char или unsigned char. Если содержимое массива char или unsigned char копируется обратно в объект, объект должен впоследствии сохранить свое первоначальное значение.

В C90 есть не по всей видимости, в явном виде упоминается корреляция, но между определением байта, определением характера и определения оператора sizeof логический вывод может быть сделан, что char типа эквивалентно байту.

Также обратите внимание, что количество бит в байте (и количество бит в char) определяется реализацией —, строго говоря, это не обязательно должно быть 8 бит. И один из них указывает на комментарий в другом месте, где DSP обычно имеют байты с числом битов, которое не равно 8.

Обратите внимание, что RFC и стандарты IETF обычно (всегда?) Используют термин 'octect' вместо 'byte' быть однозначным, что единицы, о которых они говорят, имеют ровно 8 бит - не больше, не меньше.

+0

+1. Стоит отметить, что стандарт устанавливает * нижнюю границу CHAR_BITS, но не верхнюю. Так должно быть не менее 8. – paxdiablo

Смежные вопросы