Что символ \ 0 означает в строковом литерале? - PullRequest
49 голосов
/ 17 января 2011

Рассмотрим следующий код:

char str[] = "Hello\0";

Какова длина массива str и с какими нулями он заканчивается?

Ответы [ 6 ]

85 голосов
/ 17 января 2011

sizeof str - это 7 - пять байтов для текста "Hello", плюс явный терминатор NUL плюс неявный терминатор NUL.

strlen(str) равен 5 - только пять байтов "Hello".

Ключевым моментом здесь является то, что неявный нулевой терминатор всегда добавляется - даже если строковый литерал просто заканчивается \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)

Это, однако, редко полезно, и склонно к неправильному вычислению длины строки и заканчиванию неопределенной строкой.Это также запрещено в C ++.

10 голосов
/ 17 января 2011

Длина массива равна 7, символ NUL \0 по-прежнему считается как символ, а строка по-прежнему завершается неявным \0

См. эту ссылку , чтобы увидеть рабочий пример

Обратите внимание, что если бы вы объявили str как char str[6]= "Hello\0";, длина была бы 6, потому что неявный NUL добавляется только в том случае, если он может соответствовать (чего в этом примере не может).

& раздел; 6.7.8 / p14
Массив тип символа может быть инициализирован символьная строка, опционально заключены в фигурные скобки. Sucessive символы строки символов буквальный (включая завершающий нулевой символ , если есть место или если массив неизвестного размера) инициализировать элементы массива.

Примеры * * тысяча двадцать-два 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 */

5 голосов
/ 28 октября 2015

В частности, я хочу упомянуть одну ситуацию, в которой вы можете запутаться.

В чем разница между "\ 0" и ""?

Ответ таков: "\0" представляет в массиве {0 0}, а "" - {0}.

Поскольку "\0" по-прежнему является строковым литералом, он также добавляет "\0" в конце,И "" пусто, но также добавьте "\0".

Понимание этого поможет вам глубоко понять "\0".

5 голосов
/ 17 января 2011

Испытывая мое обычное барабанное соло ПРОСТО ПОПРОБУЙТЕ , вот как вы можете ответить на такие вопросы в будущем:

$ 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% гарантированно соответствует инструментам и среде, в которой вы работаете.

3 голосов
/ 17 января 2011

Какова длина массива 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 голосов
/ 08 ноября 2018
char str[]= "Hello\0";

Это будет 7 байтов.

В памяти это будет:

48 65 6C 6C 6F 00 00
H  e  l  l  o  \0 \0

Редактировать:

  • Что делаетсимвол \ 0 означает в строке C?
    Это «конец» строки.Нулевой персонаж.В памяти это на самом деле ноль.Обычно функции, которые обрабатывают массивы символов, ищут этот символ, так как это конец сообщения.Я приведу пример в конце.

  • Какова длина массива str?(Ответ перед частью редактирования)
    7

  • и на сколько 0 заканчивается это?
    В вашем массиве есть два "пробела" с нулем;str [5] = str [6] = '\ 0' = 0

Дополнительный пример:
Предположим, у вас есть функция, которая печатает содержимое этого текстового массива.Вы можете определить его как:

char str[40];

Теперь вы можете изменить содержимое этого массива (я не буду вдаваться в подробности о том, как это сделать), чтобы оно содержало сообщение: «Это простоТест печати "В памяти у вас должно быть что-то вроде:

54 68 69 73 20 69 73 20 6a 75 73 74 20 61 20 70 72 69 6e 74
69 6e 67 20 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00

Итак, вы печатаете этот массив символов.И тогда вы хотите новое сообщение.Допустим, просто «Привет»

48 65 6c 6c 6f 00 73 20 6a 75 73 74 20 61 20 70 72 69 6e 74
69 6e 67 20 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00

Обратите внимание на 00 на стр. [5].Именно так функция печати будет знать, сколько фактически нужно отправить, несмотря на фактическую долготу вектора и всего содержимого.

...