char four [4] = «four»; Какова правильная семантика для этого утверждения?

int main(void)
{
    char four[4] = "four";
    return 0;
}

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

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

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

При компиляции программы на Си, GCC сообщает об отсутствии ошибок

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

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

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

7
задан Carl Norum 19 August 2010 в 17:06
поделиться

4 ответа

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

Длинный ответ:

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

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

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

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

 char cv [4] = "asdf"; // ошибка

неправильно сформирован, поскольку нет места для подразумеваемого завершающего ’\ 0’ . - конечный пример ]

22
ответ дан 6 December 2019 в 06:35
поделиться

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

2
ответ дан 6 December 2019 в 06:35
поделиться

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

1
ответ дан 6 December 2019 в 06:35
поделиться

Лучше было бы

char four[] = "four";
2
ответ дан 6 December 2019 в 06:35
поделиться