Подтвердить что ты не робот

Зачем писать `sizeof (char)`, если char равно 1 по стандарту?

Я делал некоторое C-кодирование, и, прочитав некоторый код C, я заметил, что есть фрагменты кода, такие как

char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);

Итак, я хочу спросить, какой еще C-ish способ выделить память для массива char? Использовать sizeof(char) и, предположительно, будущий код с любыми стандартными изменениями или опустить его и использовать номер напрямую?

4b9b3361

Ответ 1

Чем больше Cish будет

char* foo = malloc(someDynamicAmount * sizeof *foo);

ссылаясь на переменную, а не на тип, чтобы тип не нужен. И без кастования результата malloc (который есть С++ ish).

Ответ 2

Я делаю sizeof(char), чтобы сделать намерения понятными. Если кто-либо решит, что хочет, чтобы foo был int, он знает, что ему нужно будет sizeof(int), чтобы он продолжал работать.

или опустите его и используйте номер

Кроме того, это не очень хорошая практика кодирования для использования магических чисел.

Ответ 3

ИМХО лучше всего написать sizeof(*foo). Тогда вы  покрывается также, если тип изменения foo и sizeof не исправлены.

Ответ 4

Для сравнения:

float*baz = malloc(sizeof(float) * someDynamicAmount);
int  *bar = malloc(sizeof(int)   * someDynamicAmount);
char *foo = malloc(sizeof(char)  * someDynamicAmount);

Vs:

float*baz = malloc(sizeof(float) * someDynamicAmount);
int  *bar = malloc(sizeof(int)   * someDynamicAmount);
char *foo = malloc(someDynamicAmount);

Мне нравится первая версия. Вы предпочитаете второй?

Ответ 5

Вы правы, по стандарту умножение является нерелигиозным. Тем не менее, это похоже на привычку, с которой кто-то вошел, чтобы быть последовательным. Если вы всегда используете sizeof(), независимо от типа, вы никогда не забудете.

char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
int  *bar = (int  *)malloc(sizeof(int)  * someDynamicAmount);

Ответ 6

Общая идиома

T *p = malloc(N * sizeof *p);

или

T *p;
...
p = malloc(N * sizeof *p);

Таким образом, вам не нужно беспокоиться о типе.

Ответ 7

Цитирование стандарт C99, раздел 6.5.3.4 Оператор sizeof:

При применении к операнду с типом char, без знака char или подписанным char,(или его квалифицированной версии) результат равен 1. При применении к операнду с массивом type, результатом является общее количество байтов в массиве. При применении к операнду который имеет структуру или тип объединения, результатом является общее количество байтов в таком объекте, включая внутреннюю и заднюю прокладку.

То есть, sizeof char == 1 по стандарту, а не по реализации. Поэтому абсолютно правильно опускать sizeof(char) при вызове malloc() для символов и в подобных случаях. IMHO, очень маловероятно, что будущий стандарт C позволит размеру char для реализации, поскольку слишком много кода уже зависит от него как 1, а обратная совместимость очень важна в C.

Поэтому вопрос касается только стиля, а не корректности, и здесь я поддерживаю ответ AProgrammer.

Ответ 8

Написание sizeof(char) не является "будущей проверкой" вашего кода в отношении возможных изменений в стандарте. Обычно это признак полного непонимания того, что означает sizeof, и всей фундаментальной модели объектов памяти в C - то, что называется представлением типов на языке стандарта C. Причина только: оператор sizeof существует или имеет смысл, так как C указывает объекты, имеющие "представление" в памяти в терминах наименьшего возможного элемента, который равен unsigned char. Если бы не это, хранилище было бы намного более абстрактным и не было бы использования sizeof и связанной с ним арифметики указателя.

sizeof определяется в единицах char, т.е. sizeof(T)==N означает, что тип T занимает N char s. В свете этого sizeof(char) является абсолютно глупым; он пытается измерить, сколько занимает char a char.

Ответ 9

Это все зависит от стиля кодирования. Существует несколько стилей.

Чтобы ответить на вопрос, люди пишут

malloc(n * sizeof(char))

сохранить весь свой код, который использует malloc. В следующий раз им может понадобиться int, а затем они смогут написать код таким же образом,

malloc(n * sizeof(int))

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


Однако наиболее распространенным способом использования malloc в C является, возможно,

type* t = malloc(n * sizeof(*t));

или эквивалент 100%:

type* t = malloc(n * sizeof *t);

Так как оператор sizeof не оценивается для побочных эффектов, этот код безопасен, хотя переменная t еще не инициализирована.


Третий возможный стиль - это педантично правильный, который будет использовать указатели массива, поскольку то, что мы выделяем, фактически является массивом:

type (*t)[n] = malloc( sizeof(type[n]) );

Это, пожалуй, самый правильный путь, поскольку касается правильности текста. Размер массива выделяется, и мы указываем на выделенный массив указателем массива.

Однако проблема с этим стилем заключается в том, что указатели массива добавляют дополнительную сложность в синтаксис: вам нужно будет отменить этот массив как (*t)[i] вместо t[i]. Это затрудняет чтение кода. (И также в качестве примечания, если n не является целым постоянным выражением, код не будет компилироваться на старых устаревших компиляторах C.)

Ответ 10

Стиль кодирования также может быть записан как: -

char *foo = (char *)malloc(1 * someDynamicAmount);

Но это делается для того, чтобы динамически распределяющая память могла быть увеличена в соответствии с отсутствием базового типа данных, который требуется. если u хочет увеличить 100 char, оно увеличится на 100 char. Если это может не понадобиться, но если мы напишем 101 или 102, это приведет к потере памяти. выполняя его в соответствии с основным типом данных, не будет тратить время на свободное пространство памяти

Ответ 11

Стандарт преднамеренно туманно относится к размерам обычных типов. [Wikipedia]

Хотя маловероятно, что размер a char не изменится, но размер short изменился. Идиоматическим способом является:

type_t *foo = malloc(sizeof(type_t) * someDynamicAmount);

для любого типа (общего или сложного) type_t или

type_t *foo = malloc(sizeof(*foo) * someDynamicAmount);

Чтобы вы могли позже внести изменения в тип foo и изменить его только в одном месте.

Ответ 12

Подумайте о unicode и многобайтовых строках. Если char представляет один символ в строке, он может фактически занимать более одного байта, в результате чего sizeof() > 1