Какой правильный и самый безопасный способ запоминать весь массив символов с завершающим нулем символом? Я могу перечислить несколько случаев:
...
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 );
...
Варианты один и два просто неверны. Первый использует размер указателя вместо размера массива, поэтому он, вероятно, не будет записывать весь массив. Второй использует sizeof(char*)
вместо sizeof(char)
поэтому он будет писать после конца массива. Вариант 3 в порядке. Вы также можете использовать это
memset( buffer, '\0', sizeof(char)*ARRAY_LENGTH );
но sizeof(char)
гарантированно будет 1.
Идиоматическим способом является инициализация значения массива:
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 );
Поскольку вопрос постоянно меняется, я определяю:
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};
в некоторых случаях.
- Имеет ли какой-либо из них существенное преимущество перед другими?
- С какими проблемами я могу столкнуться при использовании 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);
,
Если вам абсолютно необходимо использовать необработанный массив в C ++ (это очень плохая идея), сделайте это следующим образом:
char* buffer = new char [ARRAY_LENGTH]();
Для C ++ memset
обычно является последним прибежищем некомпетентных, хотя за последние несколько месяцев я узнал, что для приемлемой производительности с текущими инструментами необходимо опуститься до этого уровня, когда реализуется собственный строковый класс.
Вместо этих необработанных массивов и т. Д., Которые могут потребоваться memset
используйте, например, std::string
(для вышеуказанного случая), std::vector
, std::array
и т.п.
Начиная с C ++ 11, я бы выбрал:
#include <array>
std::array<char, ARRAY_LENGTH> buffer{ '\0' };
buffer.fill('\0');
Option 3: memset( buffer, '\0', ARRAY_LENGTH ):
даст вам только длину массива, но на самом деле этот параметр является общим объемом байта памяти.
Option 1: memset( buffer, '\0', sizeof(buffer) ):
даст вам неправильный ответ, потому что, buffer
является char*
, sizeof(buffer)
не даст вам размер всего массива только размер переменной указателя.
Вариант 2 правильный.
Ну лично мне нравится вариант 3:
memset( buffer, '\0', ARRAY_LENGTH )
ARRAY_LENGTH
это именно то, что я хотел бы заполнить в памяти.