Как 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) не даст вам размер всего массива, только размер переменной указателя.
ну, лично мне нравится вариант 3:
memset( buffer, '', ARRAY_LENGTH )
ARRAY_LENGTH это именно то, что я хотел бы, чтобы заполнить память.