Какие языковые стандарты позволяют игнорировать нулевые терминаторы в массивах фиксированного размера?

Мы переводим код C в C ++.
Я заметил, что следующий код хорошо определен в C,

int main(){

//length is valid. '\0' is ignored
char  str[3]="abc";
}

как указано в Инициализация массива тот:

«Если известен размер массива, он может быть на единицу меньше размера
строковый литерал, в этом случае завершающий нулевой символ
проигнорировано «.

Однако, если бы я собирался создать тот же код на C ++, я получаю следующую ошибку C ++:

error: initializer-string for array of chars is too long
[-fpermissive]    char  str[3]="abc";

Я надеюсь, что кто-то может объяснить это.

Вопросы:
Является ли пример кода действительным во всех стандартах языка Си?
Это недействительно во всех стандартах языка C ++?
Есть ли причина, которая действует на одном языке, но не на другом?

21

Решение

Здесь вы видите разницу в правилах инициализации cstring в C и C ++. В §11.7.9 / 14 C11 мы имеем

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

акцент мой

Поэтому, пока массив достаточно велик для строки, исключающей нулевой терминатор, он действителен. Так

char  str[3]="abc";

Действителен C. В C ++ 14, однако, правило, которое управляет этим, содержится в [dcl.init.string] / 2 состояниях.

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

И продолжает показывать, что следующий код является ошибкой

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

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

16

Другие решения

Является ли пример кода действительным во всех стандартах языка Си?

Обратите внимание, что одновременно действует только один стандарт ISO; C2011 заменяет C99, который заменяет C89.

Я считаю, что он должен быть действительным в соответствии с любым из этих стандартов, хотя.

Это недействительно во всех стандартах языка C ++?

То же, что и выше, просто измените «действительный» на «недействительный».

Есть ли причина, которая действует на одном языке, но не на другом?

Скорее всего, он оставался действительным в C, чтобы не нарушать какой-либо устаревший код, который основывался на поведении. C ++ появился примерно через десять лет после C и попытался устранить некоторые из недостатков C, и это была одна из дыр, которые заткнули.

Многие современные языки программирования являются итерациями и улучшениями на более ранних языках; C — это B с системой типов, C ++ — это C с поддержкой OO и лучшей безопасностью типов, Java и C # — это C ++ с менее неопределенным поведением и т. Д.

5

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector