Прежде всего, вы должны помнить (или знать), что char
строки в C ++ действительно называются нулевыми окончаниями байтовыми строками .Этот бит с нулевым символом в конце является специальным символом ('\0'
), который сообщает конец строки.
Второе, что вы должны помнить (или знать), - это то, что массивы естественным образом затухаютуказатели на массивы первый элемент.В случае foo
из вашего примера, когда вы используете foo
, компилятор действительно делает &foo[0]
.
Наконец, если мы посмотрим, например, эту std::string
ссылку на конструктор вы увидите, что существует перегрузка (номер 5), которая принимает const CharT*
(с CharT
, являющимся char
для обычных char
строк).
Собираем все вместе, с
std::string banz(foo);
вы передаете указатель на первый символ foo
, и конструктор std::string
будет обрабатывать его как завершенную нулем байтовую строку.И от нахождения нулевого терминатора он знает длину строки.Фактический размер массива не имеет значения и не используется.
Если вы хотите установить размер объекта std::string
, вам нужно явно сделать это, передав аргумент длины (вариант 4 в ссылке на конструктор)):
std::string banz(foo, sizeof foo);
Это игнорирует нулевой терминатор и устанавливает длину banz
равной размеру массива.Обратите внимание, что нулевой терминатор будет по-прежнему сохраняться в строке, поэтому, передавая указатель (полученный, например, с помощью функции c_str
) в функцию, которая ожидает строку с нулевым символом в конце, строка будеткажется коротким.Также обратите внимание, что данные после нулевого терминатора будут неинициализированы и имеют неопределенное содержимое.Вы должны инициализировать эти данные, прежде чем использовать их, иначе у вас будет неопределенное поведение (а в C ++ даже чтение неопределенных данных - UB).
Как уже упоминалось в комментарии MSalters, UB при чтении неинициализированных и неопределенных данных также используется для создания объекта banz
с использованием явного размера.Обычно он работает и не приводит к каким-либо проблемам, но нарушает правила, изложенные в спецификации C ++.
Исправить это легко, хотя:
char foo[64] = { 0 };//can hold up to 64
Выше будет инициализироваться все массива в ноль.Следующий вызов strcpy
не затронет данные массива за пределами терминатора, и поэтому остаток массива будет инициализирован.