Используется 'sizeof (char)' При динамическом распределении A 'char' Резервный?

При динамическом распределении char s я всегда делал это так:

char *pCh = malloc(NUM_CHARS * sizeof(char));

Недавно мне сказали, что использование sizeof(char) является избыточным и ненужным, потому что "по определению размер a char является одним байтом", поэтому я должен/мог написать вышеприведенную строку следующим образом

char *pCh = malloc(NUM_CHARS);

Я понимаю, что размер char зависит от набора собственных символов, который используется на целевом компьютере. Например, если собственный набор символов является ASCII, a char - один байт (8 бит), а если нативный набор символов - UNICODE, то a char обязательно потребует больше байтов ( > 8 бит).

Чтобы обеспечить максимальную переносимость, не нужно было бы использовать sizeof(char), так как malloc просто выделяет 8-битные байты? Я недопонимаю malloc и sizeof(char)?

Ответ 1

Да, он избыточен, поскольку в стандарте языка указано, что sizeof (char) равно 1. Это потому, что это единица измерения, в которой измеряются вещи, поэтому, конечно, размер самого блока должен быть равен 1.

Жизнь становится странной с единицами, определенными в терминах самих себя, что просто не имеет никакого смысла. Многие люди, похоже, "хотят" предположить, что "есть 8-битные байты, а sizeof говорит мне, сколько таких есть в определенном значении". Это неправильно, это просто не так, как это работает. Верно, что могут быть платформы с более крупными символами, чем 8 бит, поэтому у нас есть CHAR_BIT.

Обычно вы всегда "знаете", когда вы все равно выделяете символы, но если вы действительно хотите включить sizeof, вам стоит подумать о том, чтобы использовать его вместо указателя:

char *pCh = malloc(NUM_CHARS * sizeof *pCh);

Это "блокирует" размер единицы предмета, на который выделяется указатель, который используется для хранения результата распределения. Эти два типа должны совпадать, если вы когда-нибудь увидите такой код:

int *numbers = malloc(42 * sizeof (float));

это огромный предупреждающий сигнал; используя указатель с левой стороны в sizeof, вы делаете такой тип ошибки невозможным, что я считаю большой победой:

int *numbers = malloc(42 * sizeof *numbers);

Кроме того, вероятно, что если вы измените имя указателя, malloc() не будет компилироваться, если бы у вас было имя (неправильного) базового типа. Существует небольшой риск, что если вы забудете звездочку (и напишите sizeof numbers вместо sizeof *numbers), вы не получите то, что хотите. На практике (для меня) этого, похоже, никогда не бывает, поскольку звездочка довольно хорошо установлена ​​как часть этого шаблона для меня.

Кроме того, это использование полагается (и подчеркивает) тот факт, что sizeof не является функцией, так как не требуется () вокруг выражения, указывающего на удаление указателя. Это хороший бонус, поскольку многие люди, похоже, хотят отрицать это.:)

Я нахожу этот образец очень удовлетворительным и рекомендую его всем.

Ответ 2

C99 draft standard раздел 6.5.3.4 В пункте 3 оператора sizeof указано:

При применении к операнду, который имеет тип char, unsigned char или подписанный char, (или его квалифицированной версии), результат равен 1. [...]

В стандартном проекте С11 это пункт 4, но формулировка такая же. Поэтому NUM_CHARS * sizeof(char) должен быть эквивалентен NUM_CHARS.

Из определения байта в 3.6 видно, что оно:

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

и в примечании 2 говорится:

Байт состоит из непрерывной последовательности бит, число которой определяется реализацией. Наименее значащий бит называется младшим битом; самый старший бит называется старшим битом.

Ответ 3

В спецификации C указано, что sizeof(char) является 1, поэтому, пока вы имеете дело с соответствующими реализациями C, он избыточен.

Единица измерения размера, используемая malloc, одинаков. malloc(120) выделяет пространство для 120 char.

A char должен быть не менее 8 бит, но может быть больше.

Ответ 4

sizeof(char) всегда будет возвращать 1, поэтому не имеет значения, используете ли вы его или nit, он не изменится. Вы можете смутить это с помощью широких символов UNICODE, которые имеют два байта, но они имеют другой тип wchar_t, поэтому вы должны использовать sizeof в этом случае.

Если вы работаете над системой, в которой байт имеет 16 бит, то sizeof(char) все равно будет возвращать 1, поскольку это будет выделено базовой архитектурой. 1 байт с 16 бит.

Ответ 5

Размеры распределения всегда измеряются в единицах char, которые по определению имеют размер 1. Если вы находитесь на 9-битной машине, malloc понимает свой аргумент как число 9-битных байтов.

Ответ 6

sizeof(char) всегда 1, но не потому, что char всегда один байт (это не обязательно), а скорее потому, что оператор sizeof возвращает размер объекта/типа в единицах char.