Как имя буквального сам по себе предполагает строковый литерал представляет собой последовательность символов, заключенных в двойных кавычках. Неявно эта последовательность символов добавляется оканчивающимся нулем.
Таким образом, любой символ, заключенный в двойные кавычки, является частью строкового литерала.
Когда строковый литерал используется для инициализации массива символов, все его символы, включая завершающий нуль, служат в качестве инициализаторов соответствующих элементов массива символов.
Каждый строковый литерал, в свою очередь, имеет тип массива символов.
Например, эта строка литерала "Hello\0Hi"
в C имеет тип char[9]
: 8 символов, заключенных в котировки плюс неявный завершающий нуль.
Таким образом, в памяти эта строка символов хранится как
{ 'H', 'e', 'l', 'l', 'o', '\0', 'H', 'i', '\0' }
Оператор sizeof
возвращает количество байтов, занимаемых объектом. Поэтому для строкового литерала над оператором sizeof
будет возвращено значение 9
- это число байтов, занятых литералом в памяти.
Если вы написали "Hello\0Hi"
, тогда компилятор не может просто удалить эту часть Hi
из буквального текста. Он должен хранить его в памяти вместе с другими символами литерала, заключенного в кавычки.
Оператор sizeof
возвращает размер в байтах любого объекта в C не только из массивов символов.
В общем массиве символов могут храниться любые необработанные данные, например, некоторые двоичные данные, считанные из двоичного файла.В этом случае эти данные не рассматриваются пользователем и программой, как строки, и в результате обрабатываются иначе, чем строки.
Стандартная функция C strlen
специально написана для массивов символов, чтобы найти длину сохраненной строки в массиве символов. Он не знает, какие данные хранятся в массиве и как они были написаны в нем. Все, что он делает, ищет первый нулевой символ в массиве символов и возвращает количество символов в массиве символов до нулевого символа.
Вы можете хранить в одном массиве символов несколько строк последовательно. Например
char s[12];
strcpy(s, "Hello");
strcpy(s + sizeof("Hello"), "World");
puts(s); // outputs "Hello"
puts(s + sizeof("Hello")); // outputs "World"
Если бы определить двумерный массив как этот
char t[2][6] = { "Hello", "World" };
то в памяти будет храниться так же, как одномерный массив выше. Таким образом, вы можете написать
char *s = (char *)t;
puts(s); // outputs "Hello"
puts(s + sizeof("Hello")); // outputs "World"
Другой пример. Стандартная функция C strtok
может разбивать одну строку, хранящуюся в массиве символов, на несколько строк, заменяя указанные пользователем разделителями нулевыми байтами. В результате массив символов будет содержать несколько строк.
Например
char s[] = "Hello World";
printf("%zu\n", sizeof(s)); // outputs 12
strtok(s, " ");
puts(s); // outputs "Hello"
puts(s + sizeof("Hello")); // outputs "World"
printf("%zu\n", sizeof(s)); // outputs 12
Последнее Printf заявление будет выдавать то же самое значение, равное 12, так как массив занимает такое же число байтов. Просто один байт в памяти, выделенной для массива, был изменен с ' '
на '\0'
.
'main()' -> 'int main (void)' пожалуйста. –
@PW, по-видимому, в стандарте c они не используют NUL, несмотря на множество таблиц ascii, где я его видел. В стандарте c используется слово * null * lowercase. –