Как 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
это именно то, что я хотел бы, чтобы заполнить память.