С++: О нулевых символах

Существуют две переменные string, m и n:

#include <string>

string m = "0100700\0"
cout << m.size() << endl; // it prints: 7

string n;
n += "0100700"
n += '\0';
cout << n.size() << endl; // it prints: 8

Я предположил, что у обоих было 8 символов, но m имел только 7 символов, а n - 8 символов. Почему это так?

Ответ 1

Прежде всего следует отметить, что std::string не имеет конструктора, который может вывести длину строкового литерала из базового массива. Он имеет конструктор, который принимает const char* и рассматривает его как строку с нулевым завершением. При этом он копирует символы, пока не найдет первый \0.

Это конструктор, используемый в string m = "0100700\0";, поэтому в первом случае ваша строка имеет длину 7. Обратите внимание, что нет другого способа получить длину массива char от указателя до его первого элемент.

Во втором примере вы добавляете символ к ранее существующему объекту std::string длиной 7. Это увеличивает длину до 8. Если вы должны были перебирать элементы строки, вы могли бы видеть что этот 8-й элемент '\0'.

for (auto c: n)
    if (c == 0) std::cout << "null terminator" << std::endl;

Чтобы инициализировать строку, содержащую символы '\0', у вас есть опции:

Используйте список инициализации:

std::string s{'a', 'b', '\0', 'd', 'e', '\0', 'g'};

Построить из другого контейнера или массива с помощью конструктора итератора std::string:

std::vector<char> v{'a', 'b', '\0', 'd', 'e', '\0', 'g'};
char c[] = {'a', 'b', '\0', 'd', 'e', '\0', 'g'};
const char* ps = "ab\0de\0g";

std::string s0(std::begin(v), std::end(v));
std::string s1(std::begin(c), std::end(c));
std::string s2(ps, ps + 8);

Ответ 2

В первом примере

 string m = "0100700\0";

Переменная string построена из символьного литерала и принимает все символы до первого найденного символа '\0'.

2-й пример, тем не менее, показывает, что вы можете добавить произвольное количество дополнительных символов '\0' в std::string и увеличить его размер.


Чтобы ответить на вопрос с вашего комментария:

Чтобы инициализировать строку из литерала, содержащего символы '\0', которые вы указали, либо укажите явно

string m("0100700\0",8);

или вы можете использовать конструктор, используя итератор first и last:

 const char x[] = "0100700\0";
 string m(std::begin(x),std::end(x));