char four [4] = "четыре";Какова правильная семантика для этого утверждения? - PullRequest
7 голосов
/ 19 августа 2010
int main(void)
{
    char four[4] = "four";
    return 0;
}

При компиляции в виде программы на C ++ G ++ сообщает

xxx.cpp: в функции int main ():

xxx.cpp: 3: ошибка: строка инициализатора для массива символов слишком длинная

При компиляции программы на C GCC не сообщает об ошибке.

Мне кажется, что назначение правильно копирует все 4 байта в переменную, как я и ожидал.

Так что мой вопрос сводится к .....

Является ли наблюдаемое поведение в C правильным или я где-то касаюсь неопределенного поведения, или это вообще что-то еще?

Ответы [ 4 ]

22 голосов
/ 19 августа 2010

Краткий ответ: ваш код является допустимым C, но не допустимым C ++.

Лонг Асвер:

"four" на самом деле длиной 5 символов - для вас добавлено \0. В разделе 6.7.8 Инициализация , параграф 13, стандарт C говорит:

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

Таким образом, \0 просто игнорируется в вашей программе, когда он компилируется как C. C ++ относится к нему по-другому. Фактически, этот конкретный случай вызывается явно в спецификации C ++ (Раздел 8.5.2 Массивы символов , пункт 2):

Не должно быть больше инициализаторов, чем элементов массива. [ Пример:

char cv[4] = "asdf";  // error

плохо сформирован, так как нет места для подразумеваемого следа ’\0’. - конец примера ]

2 голосов
/ 19 августа 2010

Лучше было бы

char four[] = "four";
2 голосов
/ 19 августа 2010

Строка "four" на самом деле содержит пять байтов: четыре буквы плюс нулевой байт (\ 0) в качестве ограничителя строки. Прошло много времени с тех пор, как я написал C или C ++, но я предполагаю, что компилятор C молча игнорирует его по любой причине.

1 голос
/ 19 августа 2010

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

...