Зачем писать `sizeof (char)`, если char равен 1 по умолчанию? - PullRequest
49 голосов
/ 30 августа 2011

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

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

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

Ответы [ 12 ]

65 голосов
/ 30 августа 2011

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

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

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

29 голосов
/ 30 августа 2011

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

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

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

25 голосов
/ 30 августа 2011

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

11 голосов
/ 30 августа 2011

Сравнить:

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);

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

7 голосов
/ 30 августа 2011

Общая идиома

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

или

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

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

7 голосов
/ 30 августа 2011

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

char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
int  *bar = (int  *)malloc(sizeof(int)  * someDynamicAmount);
2 голосов
/ 26 марта 2012

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

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

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

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

1 голос
/ 30 августа 2011

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

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

0 голосов
/ 27 октября 2017

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

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

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 не является целочисленным константным выражением, код не будет компилироваться на старых устаревших компиляторах Си.)

0 голосов
/ 30 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...