C инициализатор строки не включает терминатор? - PullRequest
5 голосов
/ 23 января 2009

Меня немного смущают следующие фрагменты кода C:

printf("Peter string is %d bytes\n", sizeof("Peter")); // Peter string is 6 bytes

Это говорит мне, что когда C компилирует строку в двойных кавычках, он автоматически добавит дополнительный байт для нулевого терминатора.

printf("Hello '%s'\n", "Peter");

Функция printf знает, когда прекратить чтение строки "Питер", потому что она достигает нулевого терминатора, поэтому ...

char myString[2][9] = {"123456789", "123456789" };
printf("myString: %s\n", myString[0]);

Здесь printf печатает все 18 символов, потому что нет нулевых терминаторов (и они не подойдут, если не взять 9). Разве C не добавляет нулевой терминатор в определение переменной?

Ответы [ 7 ]

24 голосов
/ 23 января 2009

Ваша строка [2] [9]. Это [9]: ['1', '2' и т. Д. '' 8 ',' 9 ']. Поскольку вы дали ему место только для 9 символов в первом измерении массива, а поскольку вы использовали все 9, в нем нет места для размещения символа \ 0. переопределить ваш массив символов:

char string[2][10] = {"123456789", "123456789"};

И это должно работать.

5 голосов
/ 23 января 2009

Конечно, вы просто не оставляете достаточно места для байта '\ 0'. Делаем это:

char string[2][10] = { "123456789", "123456789" };

Будет работать так, как вы ожидаете (просто напечатает 9 символов).

3 голосов
/ 23 января 2009

Если вы скажете C, что массив имеет заданный размер, C не сможет увеличить массив. Было бы непослушным, если бы это было так! Помните, что не каждый массив char содержит строку с нулевым символом в конце. Иногда массив (в том виде, в котором он используется) действительно представляет собой массив (отдельных) символов char. Компилятор не знает, что вы делаете, и не может читать ваши мысли.

Вот почему C позволяет вам инициализировать массив символов, где нулевой терминатор не подходит, но все остальное будет соответствовать. Попробуйте ваш пример со строкой на один байт длиннее, и компилятор будет жаловаться.

Обратите внимание, что ваш пример будет скомпилирован, но не сделает то, что вы ожидаете, поскольку строки не заканчиваются нулем (если ваш компилятор не делает что-то необычное). С GCC, работающим на вашем примере, я вижу нужную строку, за которой следует мусор.

2 голосов
/ 23 января 2009

C допускает неопределенные строки, C ++ - нет.

C позволяет использовать массивы символов инициализируется строковыми константами. Это также позволяет строковую константу инициализатор должен содержать ровно один больше символа, чем массив инициализирует, то есть неявное завершающий нулевой символ Строка может быть проигнорирована. Например:

char  name1[] =  "Harry";   // Array of 6 char

char  name2[6] = "Harry";   // Array of 6 char

char  name3[] =  { 'H', 'a', 'r', 'r', 'y', '\0' };
                            // Same as 'name1' initialization

char  name4[5] = "Harry";   // Array of 5 char, no null char 

C ++ также позволяет использовать массивы символов инициализируется строковыми константами, но всегда включает завершающий ноль символ в инициализации. таким образом последний инициализатор (name4) в пример выше недействителен в C ++.

2 голосов
/ 23 января 2009

Альтернативно, вы можете использовать:

char* myString[2] = {"123456789", "123456789" };

Таким образом, инициализатор вычисляет правильный размер для строк с нулевым символом в конце.

0 голосов
/ 23 января 2009

Байт '\ 0' не является проблемой. Большую часть времени, если у вас есть это:

char code[9] = "123456789";

Следующий байт будет за пределами переменной, но будет неиспользуемой памятью и, скорее всего, будет 0 (если вы не malloc() и не установите значения перед их использованием). Так что большую часть времени это работает, даже если это плохо для вас.

Если вы используете gcc, вы также можете использовать флаг -Wall или один из других (миллионов) флагов предупреждения. Это может помочь (не уверен).

0 голосов
/ 23 января 2009

Есть ли причина, по которой компилятор не предупреждает, что недостаточно места для 0 байтов? Я получаю предупреждение, если пытаюсь добавить еще 9, которые не подходят, но, похоже, не заботится о том, чтобы сбросить 0 байт?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...