Почему «строка инициализатора для массива символов слишком длинна» прекрасно компилируется в C & amp; не в C ++?

Следующая программа прекрасно компилируется в C с предупреждениями, но не компилируется в C ++. Зачем? Какова причина?

#include <stdio.h>
int main(void)
{
char a[5]="Hello";
a[0]='y';
puts(a);
for(int i=0;i<5;i++)
printf("%c",a[i]);
return 0;
}

Предупреждение:

Warning:[Error] initializer-string for array of chars is too long [-fpermissive] enabled by default

Но если программа скомпилирована как программа C ++, то компилятор C ++ выдает следующую ошибку:

[Error] initializer-string for array of chars is too long [-fpermissive]

Я использую компилятор GCC 4.8.1.

5

Решение

Краткий ответ: потому что C и C ++ — это разные языки с разными правилами.

Длинный ответ: в обоих случаях причина в том, что массив слишком мал для строкового литерала. Литерал состоит из пяти видимых символов с нулевым терминатором на конце, поэтому общий размер равен 6.

В C вы можете инициализировать массив слишком длинной строкой; лишние символы просто игнорируются:

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

Компилятор предупреждает, что строка слишком велика, поскольку почти наверняка указывает на ошибку; но он не может отклонить код, если вы не скажете, чтобы он воспринимал предупреждения как ошибки.

В C ++ инициализатору не разрешено быть больше, чем массив:

C ++ 11 8.5.2 / 2: Инициализаторов не должно быть больше, чем элементов массива.

поэтому для этого языка компилятор должен выдать ошибку.

В обоих языках, когда вы хотите, чтобы символьный массив соответствовал размеру инициализатора строкового литерала, вы можете не указывать размер, и компилятор сделает все правильно.

char a[] = "hello";  // size deduced to be 6
22

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

Проблема в нижней строке

char a[5]="Hello";

Нет места для хранения завершающего нуля.

По умолчанию, gcc не выдает никаких ошибок для этого случая с -fpermissive опция включена. Так что компилирует нормально в C,

Согласно требованию от языковых стандартов,

  • ЗаC99 стандарт, глава 6.7.9, пункт 14,

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

  • За C++11, глава 8.5.2, пункт 2

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

Итак, код компилируется (с предупреждениями) с gcc, выдает ошибку с g++,

10

Допустимая строка в C и C ++ должна иметь \0 терминатор и в

char a[5]="Hello";

Там нет места для нулевого терминатора и не является допустимой строкой.

Так что это может не быть ошибкой в ​​C, но вы обязательно столкнетесь с проблемами при использовании встроенных строковых функций, таких как strlen() и семья.

5

Потому что «Привет» 6 charс долго и г ++ без -fpermissive не будет инициализировать 5 char массив с ним, но GCC будет.

3
По вопросам рекламы [email protected]