Ответ 1
Чем больше Cish будет
char* foo = malloc(someDynamicAmount * sizeof *foo);
ссылаясь на переменную, а не на тип, чтобы тип не нужен. И без кастования результата malloc (который есть С++ ish).
Я делал некоторое C-кодирование, и, прочитав некоторый код C, я заметил, что есть фрагменты кода, такие как
char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
Итак, я хочу спросить, какой еще C-ish способ выделить память для массива char? Использовать sizeof(char)
и, предположительно, будущий код с любыми стандартными изменениями или опустить его и использовать номер напрямую?
Чем больше Cish будет
char* foo = malloc(someDynamicAmount * sizeof *foo);
ссылаясь на переменную, а не на тип, чтобы тип не нужен. И без кастования результата malloc (который есть С++ ish).
Я делаю sizeof(char)
, чтобы сделать намерения понятными. Если кто-либо решит, что хочет, чтобы foo был int
, он знает, что ему нужно будет sizeof(int)
, чтобы он продолжал работать.
или опустите его и используйте номер
Кроме того, это не очень хорошая практика кодирования для использования магических чисел.
ИМХО лучше всего написать sizeof(*foo)
. Тогда вы
покрывается также, если тип изменения foo и sizeof не исправлены.
Для сравнения:
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);
Мне нравится первая версия. Вы предпочитаете второй?
Вы правы, по стандарту умножение является нерелигиозным. Тем не менее, это похоже на привычку, с которой кто-то вошел, чтобы быть последовательным. Если вы всегда используете sizeof()
, независимо от типа, вы никогда не забудете.
char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
int *bar = (int *)malloc(sizeof(int) * someDynamicAmount);
Общая идиома
T *p = malloc(N * sizeof *p);
или
T *p;
...
p = malloc(N * sizeof *p);
Таким образом, вам не нужно беспокоиться о типе.
Цитирование стандарт C99, раздел 6.5.3.4 Оператор sizeof
:
При применении к операнду с типом char, без знака char или подписанным char,(или его квалифицированной версии) результат равен 1. При применении к операнду с массивом type, результатом является общее количество байтов в массиве. При применении к операнду который имеет структуру или тип объединения, результатом является общее количество байтов в таком объекте, включая внутреннюю и заднюю прокладку.
То есть, sizeof char == 1
по стандарту, а не по реализации. Поэтому абсолютно правильно опускать sizeof(char)
при вызове malloc()
для символов и в подобных случаях. IMHO, очень маловероятно, что будущий стандарт C позволит размеру char
для реализации, поскольку слишком много кода уже зависит от него как 1, а обратная совместимость очень важна в C.
Поэтому вопрос касается только стиля, а не корректности, и здесь я поддерживаю ответ AProgrammer.
Написание sizeof(char)
не является "будущей проверкой" вашего кода в отношении возможных изменений в стандарте. Обычно это признак полного непонимания того, что означает sizeof
, и всей фундаментальной модели объектов памяти в C - то, что называется представлением типов на языке стандарта C. Причина только: оператор sizeof
существует или имеет смысл, так как C указывает объекты, имеющие "представление" в памяти в терминах наименьшего возможного элемента, который равен unsigned char
. Если бы не это, хранилище было бы намного более абстрактным и не было бы использования sizeof
и связанной с ним арифметики указателя.
sizeof
определяется в единицах char
, т.е. sizeof(T)==N
означает, что тип T
занимает N
char
s. В свете этого sizeof(char)
является абсолютно глупым; он пытается измерить, сколько занимает char
a char
.
Это все зависит от стиля кодирования. Существует несколько стилей.
Чтобы ответить на вопрос, люди пишут
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.)
Стиль кодирования также может быть записан как: -
char *foo = (char *)malloc(1 * someDynamicAmount);
Но это делается для того, чтобы динамически распределяющая память могла быть увеличена в соответствии с отсутствием базового типа данных, который требуется. если u хочет увеличить 100 char, оно увеличится на 100 char. Если это может не понадобиться, но если мы напишем 101 или 102, это приведет к потере памяти. выполняя его в соответствии с основным типом данных, не будет тратить время на свободное пространство памяти
Стандарт преднамеренно туманно относится к размерам обычных типов. [Wikipedia]
Хотя маловероятно, что размер a char
не изменится, но размер short
изменился. Идиоматическим способом является:
type_t *foo = malloc(sizeof(type_t) * someDynamicAmount);
для любого типа (общего или сложного) type_t или
type_t *foo = malloc(sizeof(*foo) * someDynamicAmount);
Чтобы вы могли позже внести изменения в тип foo и изменить его только в одном месте.
Подумайте о unicode и многобайтовых строках. Если char представляет один символ в строке, он может фактически занимать более одного байта, в результате чего sizeof() > 1