Рассмотрим следующий код:
char str[]= "Hello\0";
Какова длина массива str и с каким количеством окон заканчивается?
Рассмотрим следующий код:
char str[]= "Hello\0";
Какова длина массива str и с каким количеством окон заканчивается?
sizeof str
- 7 - пять байтов для текста "Hello", плюс явный терминатор NUL плюс неявный терминатор NUL.
strlen(str)
- 5 - только пять байтов "Hello".
Ключевым моментом здесь является то, что неявный терминатор nul всегда добавляется, даже если строковый литерал заканчивается на \0
. Конечно, strlen
просто останавливается при первом \0
- он не может отличить разницу.
Есть одно исключение из неявного правила терминатора NUL - если вы явно указываете размер массива, строка будет усечена, чтобы соответствовать:
char str[6] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 6 (with one NUL)
char str[7] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 7 (with two NULs)
char str[8] = "Hello\0"; // strlen(str) = 5, sizeof(str) = 8 (with three NULs per C99 6.7.8.21)
Это, однако, редко полезно и склонно просчитывать длину строки и заканчиваться неисчерпаемой строкой. Это также запрещено в С++.
Длина массива равна 7, символ NUL \0
по-прежнему считается символом, а строка все равно заканчивается неявным \0
Смотрите эту ссылку, чтобы увидеть рабочий пример
Обратите внимание, что если бы вы объявили str
как char str[6]= "Hello\0";
, длина была бы 6, потому что неявный NUL добавляется только в том случае, если он может поместиться (чего не может быть в этом примере.)
& раздел; 6.7.8/p14
Массив тип символа может быть инициализирован символьный строковый литерал, необязательно заключенные в фигурные скобки. Sucessive символы символьной строки буквальный (включая завершающий null character , если есть место, или если массив неизвестного размера) инициализируйте элементы массива.
char str[] = "Hello\0"; /* sizeof == 7, Explicit + Implicit NUL */
char str[5]= "Hello\0"; /* sizeof == 5, str is "Hello" with no NUL (no longer a C-string, just an array of char). This may trigger compiler warning */
char str[6]= "Hello\0"; /* sizeof == 6, Explicit NUL only */
char str[7]= "Hello\0"; /* sizeof == 7, Explicit + Implicit NUL */
char str[8]= "Hello\0"; /* sizeof == 8, Explicit + two Implicit NUL */
Разбивая свое обычное барабанное соло JUST TRY IT, вот как вы можете ответить на такие вопросы в будущем:
$ cat junk.c
#include <stdio.h>
char* string = "Hello\0";
int main(int argv, char** argc)
{
printf("-->%s<--\n", string);
}
$ gcc -S junk.c
$ cat junk.s
... устраняя ненужные части...
.LC0:
.string "Hello"
.string ""
...
.LC1:
.string "-->%s<--\n"
...
Обратите внимание на то, как строка, которую я использовал для printf, просто "-->%s<---\n"
, а глобальная строка состоит из двух частей: "Hello"
и ""
. Ассемблер GNU также завершает строки с неявным символом NUL
, поэтому тот факт, что первая строка (.LC0) находится в этих двух частях, указывает на наличие двух NUL
s. Таким образом, строка имеет длину 7 байтов. Как правило, если вы действительно хотите знать, что делает ваш компилятор с определенным куском кода, изолируйте его в таком фиктивном примере, как это, и посмотрите, что он делает, используя -S
(для GNU - MSVC имеет флаг также для вывода ассемблера, но Я не знаю, что это за руку). Вы узнаете много о том, как работает ваш код (или не работает в зависимости от обстоятельств), и вы получите ответ быстро, который на 100% гарантированно соответствует инструментам и среде, в которой вы работаете.
Какова длина массива str и с каким количеством окон заканчивается?
int main() {
char str[] = "Hello\0";
int length = sizeof str / sizeof str[0];
// "sizeof array" is the bytes for the whole array (must use a real array, not
// a pointer), divide by "sizeof array[0]" (sometimes sizeof *array is used)
// to get the number of items in the array
printf("array length: %d\n", length);
printf("last 3 bytes: %02x %02x %02x\n",
str[length - 3], str[length - 2], str[length - 1]);
return 0;
}
В частности, я хочу упомянуть одну ситуацию, с помощью которой вы можете смутить.
В чем разница между "\ 0" и ""?
Ответ заключается в том, что "\0"
представляет в массиве {0 0}
и ""
is {0}
.
Потому что "\0"
по-прежнему является строковым литералом, и он также добавит "\0"
в конец. И ""
пуст, но также добавляет "\0"
.
Понимание этого поможет вам глубоко понять "\0"
.