Необходимо ли умножать на sizeof (char) при манипулировании памятью?

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

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

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

или я могу положиться на sizeof (char ) всегда быть 1 и просто пропустить умножение

char* buffer = malloc( N );

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

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

8 ответов


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


по определению, 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);

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


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

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


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

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

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

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

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

выводит 1, всегда, на всех соответствующих реализациях C.

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

вместо

char *str;

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

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

char *str;

str = malloc(N * sizeof *str);

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


не надо. См.здесь (например).

sizeof(char) определено стандартом C, чтобы всегда быть 1


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


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

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

количество битов в представлении символьного типа неуместный. По определению число байт в байт тип персонажа один.

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


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

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

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

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