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

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

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

int main(){

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

как указано в инициализации массива, который:

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

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

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

Я надеюсь, кто-то сможет изложить это.

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

4b9b3361

Ответ 1

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

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

акцент мой

До тех пор, пока массив достаточно велик, чтобы строка, исключая нулевой ограничитель, действительна. Итак,

char  str[3]="abc";

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

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

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

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

Итак, на С++ у вас должно быть достаточно хранилища для всего строкового литерала, включая нулевой терминатор.

Ответ 2

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

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

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

Недействителен ли он во всех языковых стандартах на С++?

Как и выше, просто измените значение "valid" на "invalid".

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

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

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