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

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

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

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

8 ответов


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

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

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


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

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

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

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

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

для C (предполагая, что malloc вместо new[]), вы можете использовать

memset( buffer, 0, ARRAY_LENGTH );

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

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

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

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

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

если вопрос только в том, " как правильно называть memset " вместо "каков наилучший способ обнулить этот массив", то либо 2b, либо 3 является правильным. 1 и 2a ошибочны.

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

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

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

еще один вариант, любимый программистами" C++ - это не 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}; в некоторых случаях.


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

1-й ошибается, потому что sizeof(buffer) == sizeof(char*).

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

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

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

buffer[0] = '';

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

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


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

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

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

вместо этих необработанных массивов и т. д., который может потребоваться memset, например:std::string (для выше case),std::vector, std::array etc.


Так как C++ 11, я бы выбрал:

#include <array>

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

buffer.fill('');

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

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

2 является правильным.

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

memset( buffer, '', ARRAY_LENGTH )

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