Подтвердить что ты не робот

Ошибка компилятора при инициализации массива с фиксированным размером 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. Итак, почему компилятор здесь не дает ошибку?

Есть ли способ изменить мою декларацию/определение/инициализацию, чтобы в этом случае была отмечена ошибка?

4b9b3361

Ответ 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.