it-swarm.com.ru

Что символ\0 означает в строковом литерале?

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

char str[] = "Hello\0";

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

47
UmmaGumma

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)

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

84
bdonlan

Длина массива равна 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 */
10
SiegeX

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

$ 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) находится в этих двух частях, указывает на наличие двух NULs. Таким образом, длина строки составляет 7 байтов. Обычно, если вы действительно хотите узнать, что ваш компилятор делает с определенным ломтем кода, выделите его в фиктивном примере, подобном этому, и посмотрите, что он делает, используя -S (для GNU - MSVC также имеет флаг для ассемблера выходной, но я не знаю, это с рук). Вы узнаете много нового о том, как работает ваш код (или не работает в зависимости от обстоятельств), и вы быстро получите ответ, который на 100% гарантированно соответствует инструментам и среде, в которой вы работаете.

5
JUST MY correct OPINION

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

Какая разница между "\ 0" и ""?

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

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

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

4
YongHao Hu

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

Давайте разберемся:

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;
}
3
Fred Nurk
char str[]= "Hello\0";

Это было бы 7 байтов.

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

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

Правка: 

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

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

  • а на сколько 0s это заканчивается?
    В вашем массиве есть два «пробела» с нулем; ул [5] = ул [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]. Таким образом, функция печати будет знать, сколько фактически нужно отправить, несмотря на фактическую долготу вектора и всего содержимого.

0
L. Lopez