Ошибка компилятора при инициализации массива с фиксированным размером char без достаточного количества нулевого ограничителя
Предположим, что у меня есть следующие c char массивы:
char okaysize4[5] = "four"; // line 5
char toosmall4[4] = "four"; // line 6
char toosmall3[3] = "four"; // line 7
Когда я компилирую с gcc 4.4.7, я получаю следующую ошибку:
array.c: 7: предупреждение: строка инициализации для массива символов слишком длинная
Эта ошибка ожидается для строки 7, так как я пытаюсь записать 5 символов ("four" + \0)
в массив из 3 элементов.
Также не ожидается ошибка для строки 5, поскольку массив 5 элементов достаточно велик.
Однако я удивлен, что подобная ошибка для строки 6 не возникает. Что заканчивается тем, что инициализируется в toosmall4
, является неисчерпаемой строкой, которая может вызвать всевозможные проблемы.
Я понимаю, что строковый литерал c "four"
должен содержать пять символов, из-за нулевого терминатора. Фактически sizeof("four")
равно 5. Итак, почему компилятор здесь не дает ошибку?
Есть ли способ изменить мою декларацию/определение/инициализацию, чтобы в этом случае была отмечена ошибка?
Ответы
Ответ 1
Это ожидаемое поведение для строки 6, из черновик стандарта C99 раздел 6.7.8
В параграфе 14 инициализации говорится (основное внимание):
Массив типа символа может быть инициализирован символьной строкой буквальный, необязательно заключенный в фигурные скобки. Последовательные символы символьный строковый литерал (, включающий завершающий нулевой символ если есть место или массив неизвестного размера), выполните инициализацию элементов массива.
В стандартном проекте C11 соответствующий раздел с аналогичной формулировкой представляет собой пункт 14 6.7.9
, а в качестве C часто задаваемых вопросов:
Поэтому массив не является истинной строкой C и не может использоваться с strcpy, printf% s и т.д.
Как отметил Кейт Томпсон, С++ более строг, соответствующий раздел в проекте стандарта С++ гласит следующее:
Не должно быть больше инициализаторов, чем элементов массива. [Пример:
char cv[4] = "asdf"; // error
плохо сформировалось, поскольку для подразумеваемого конечного \0 не существует пространства. -end пример]
Ответ 2
Он легальный, toosmall4
не является строкой, а допустимым массивом char (без конечного нулевого символа).
Ссылка: C FAQ.