Как записать в массив char символ с нулевым завершающим символом?

Какой правильный и самый безопасный способ запоминать весь массив символов с завершающим нулем символом? Я могу перечислить несколько случаев:

...
char* buffer = new char [ARRAY_LENGTH];

//Option 1:             memset( buffer, '\0', sizeof(buffer) );
//Option 2 before edit: memset( buffer, '\0', sizeof(char*) * ARRAY_LENGTH );
//Option 2 after edit:  memset( buffer, '\0', sizeof(char) * ARRAY_LENGTH );
//Option 3:             memset( buffer, '\0', ARRAY_LENGTH );
...
  • Имеет ли какой-либо из них существенное преимущество перед другими?
  • С какими проблемами я могу столкнуться при использовании 1, 2 или 3?
  • Каков наилучший способ обработать этот запрос?

13

Решение

Варианты один и два просто неверны. Первый использует размер указателя вместо размера массива, поэтому он, вероятно, не будет записывать весь массив. Второй использует sizeof(char*) вместо sizeof(char) поэтому он будет писать после конца массива. Вариант 3 в порядке. Вы также можете использовать это

memset( buffer, '\0', sizeof(char)*ARRAY_LENGTH );

но sizeof(char) гарантированно будет 1.

17

Другие решения

Идиоматическим способом является инициализация значения массива:

char* buffer = new char [ARRAY_LENGTH]();

Опция 1 только устанавливает первый sizeof(char*) байтов до 0, или сталкивается с неопределенным поведением, если ARRAY_LENGHT < sizeof(char*),

Вариант 2 сталкивается с неопределенным поведением, потому что вы пытаетесь установить больше, чем ARRAY_LENGTH байтов. sizeof(char*) почти наверняка больше 1.

Так как это C ++, хотя (нет new в с), я предлагаю вам использовать std::string вместо.

Для С (при условии malloc вместо new[]), ты можешь использовать

memset( buffer, 0, ARRAY_LENGTH );
13

Поскольку вопрос постоянно меняется, я определяю:

1: memset( buffer, '\0', sizeof(buffer) );

2а: memset( buffer, '\0', sizeof(char*) * ARRAY_LENGTH );

2b: memset( buffer, '\0', sizeof(char) * ARRAY_LENGTH );

3: memset( buffer, '\0', ARRAY_LENGTH );

Если вопрос просто, «как правильно позвонить memset«вместо того, чтобы» как лучше всего обнулить этот массив «, тогда либо 2b, либо 3 — это правильно. 1 и 2a — неверно.

У вас может быть война стиля более 2б против 3: стоит ли включать sizeof(char) или нет — некоторые люди оставляют это, потому что это избыточно (я обычно делаю), другие люди помещают это, чтобы создать вид согласованности с тем же кодом, устанавливающим массив int, То есть они всегда умножают размер на количество элементов, даже если они знают, что размер равен 1. Один из возможных выводов состоит в том, что «самый безопасный» способ запоминания массива, на который указывает buffer является:

std::memset(buffer, 0, sizeof(*buffer) * ARRAY_LENGTH);

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

Другой вариант, любимый программистами «C ++ is C», это:

/* never mind how buffer is allocated */
std::fill(buffer, buffer + ARRAY_LENGTH, 0);

Если вам не все равно, вы можете сами проверить, оптимизирует ли ваш компилятор тот же код, для которого он оптимизирует эквивалентный вызов std::memset,

char *buffer = new char [ARRAY_LENGTH](); изящен, но практически бесполезен в C ++ на практике, потому что вы почти никогда не выделяете массив new на первом месте.

std::string buffer(ARRAY_LENGTH, 0); представляет особый способ управления буфером, который может или не может быть тем, что вы хотите, но часто это. Есть много чего сказать char buffer[ARRAY_LENGTH] = {0}; в некоторых случаях.

5

  • Имеет ли какой-либо из них существенное преимущество перед другими?
  • С какими проблемами я могу столкнуться при использовании 1, 2 или 3?

1-е неправильно, потому что sizeof(buffer) == sizeof(char*),

2 и 3 в порядке.

  • Каков наилучший способ обработать этот запрос?

Почему не просто

buffer[0] = '\0';

Если это char массив, зачем беспокоиться с остальными персонажами? Когда первый байт установлен в ноль, у вас есть эквивалент "" в вашем buffer,

Конечно, если вы действительно настаиваете на том, чтобы все buffer обнулите, используйте ответ с std::fill — это правильный путь. Я имею в виду std::fill(buffer, buffer + ARRAY_LENGTH, 0);,

3

Если вам абсолютно необходимо использовать необработанный массив в C ++ (это очень плохая идея), сделайте это следующим образом:

char* buffer = new char [ARRAY_LENGTH]();

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

Вместо этих необработанных массивов и т. Д., Которые могут потребоваться memsetиспользуйте, например, std::string (для вышеуказанного случая), std::vector, std::array и т.п.

2

Начиная с C ++ 11, я бы выбрал:

#include <array>

std::array<char, ARRAY_LENGTH> buffer{ '\0' };

buffer.fill('\0');
1

Option 3: memset( buffer, '\0', ARRAY_LENGTH ): даст вам только длину массива, но на самом деле этот параметр является общим объемом байта памяти.

Option 1: memset( buffer, '\0', sizeof(buffer) ): даст вам неправильный ответ, потому что, buffer является char*, sizeof(buffer) не даст вам размер всего массива только размер переменной указателя.

Вариант 2 правильный.

0

Ну лично мне нравится вариант 3:

memset( buffer, '\0', ARRAY_LENGTH )

ARRAY_LENGTH это именно то, что я хотел бы заполнить в памяти.

0
По вопросам рекламы [email protected]