Нужно ли умножать на sizeof (char) при манипулировании памятью? - PullRequest
15 голосов
/ 18 июня 2009

При использовании malloc и аналогичных манипуляциях с памятью могу ли я полагаться, что sizeof (char) всегда равен 1?

Например, мне нужно выделить память для N элементов типа char. Умножается на sizeof( char ) необходимо:

char* buffer = malloc( N * sizeof( char ) );

или я могу полагаться на то, что sizeof (char) всегда равен 1, и просто пропускаю умножение

char* buffer = malloc( N );

Я полностью понимаю, что sizeof оценивается во время компиляции, а затем компилятор может даже скомпилировать умножение, поэтому потеря производительности будет минимальной и, скорее всего, нулевой.

Я спрашиваю в основном о ясности и переносимости кода. Это умножение когда-либо необходимо для char типа?

Ответы [ 8 ]

27 голосов
/ 18 июня 2009

По определению, sizeof (char) всегда равен 1. Один байт - это размер символа в C, независимо от количества бит в байте (8 на обычном настольном процессоре).

Типичным примером, когда один байт не равен 8 битам, является PDP-10 и другие старые мини-подобные архитектуры с 9/36 битными байтами. Но я считаю, что байты, которые не равны 2 ^ N, становятся чрезвычайно необычными

Кроме того, я думаю, что это лучший стиль:

char* buf1;
double* buf2;

buf1 = malloc(sizeof(*buf1) * N);
buf2 = malloc(sizeof(*buf2) * N);

потому что он работает независимо от типа указателя.

14 голосов
/ 18 июня 2009

sizeof(char) всегда равно 1, независимо от типа манипуляции с памятью.

Однако sizeof(TCHAR) может отличаться в зависимости от параметров вашего компилятора.

11 голосов
/ 18 июня 2009

Я считаю, что это анти-паттерн . Это говорит о том, что программист не совсем знал, что он делает, что немедленно бросает остальную часть кода в сомнительный свет.

Конечно, это не (цитируя Википедию) "неэффективно", но я нахожу это "далеко не оптимальным". Он ничего не стоит во время выполнения, но он загромождает код ненужным мусором, все время сигнализируя, что кто-то посчитал это необходимым.

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

Вполне возможно, и настоятельно рекомендуется, когда это возможно, использовать sizeof в других выражениях, тогда он даст размер значения выражения:

char a;
printf("A char's size is %u\n", (unsigned int) sizeof a);

Это будет печатать 1, всегда, на всех соответствующих реализациях C.

Я также полностью согласен с Дэвидом Курнапо и считаю, что повторение типа name при malloc() -all также будет своего рода анти-паттерном.

вместо

char *str;

str = malloc(N * sizeof (char));

, что многие пишут для выделения строкового буфера с N-символьной емкостью, я бы сказал

char *str;

str = malloc(N * sizeof *str);

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

6 голосов
/ 19 июня 2009

Хотя это и не обязательно, я считаю хорошей практикой оставлять размер size (char), поскольку он делает код более читабельным и позволяет избежать использования магического числа. Кроме того, если код необходимо изменить позже, чтобы вместо символа он искажал размер чего-либо в указателе для этого объекта, его было бы проще изменить, чем если бы у вас была только «1».

6 голосов
/ 18 июня 2009

Это не обязательно. См. здесь (например).

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

3 голосов
/ 07 февраля 2010

Из "Нового стандарта С. Экономический и культурный комментарий".

  1. Статистика: 2,0% от sizeof взято с char и 1,5% - с unsigned char. Страница 1033 в версии 1.2 книги.
  2. стр. 1037.

Количество битов в представлении символьного типа равно не имеет значения. По определению количество байтов в байте тип символа один.

Рекомендации по кодированию Разработчики иногда ассоциировать байт как всегда содержащий восемь бит На хостах где то тип символа 16 бит, это может привести к неверному предположению, что применение sizeof к типу символов вернет значение 2. Эти вопросы обсуждаются в другом месте.

3 голосов
/ 18 июня 2009

Что еще нужно помнить, это то, что компилятор статически знает, что значение sizeof (char) равно 1, а также знает, что умножение числа на статическое 1 означает, что умножение не требуется; компилятор оптимизирует его. Проблемы исполнения не должны входить в рассмотрение по этим основаниям.

0 голосов
/ 18 июня 2009

Использование sizeof (char) делает ваш код более читабельным и переносимым.

На x86 мы все знаем, что символ равен 1 байту. Но явное его написание помогает прояснить ваши намерения, что всегда хорошо.

Кроме того, что если ваш код будет помещен на другую платформу, где символ не равен 1 байту. Что, если символ был только 4 битами вместо этого?

Согласен, в этом нет необходимости, но он не замедляет время выполнения и окупится в том редком случае, когда вам нужно перенести код на другую архитектуру.

...