Почему максимальная длина строкового литерала C отличается от max char []? - программирование
Подтвердить что ты не робот

Почему максимальная длина строкового литерала C отличается от max char []?

Разъяснение. Учитывая, что строковый литерал можно переписать как const char[] (см. ниже), накладывая меньшую максимальную длину на литералы, чем на char[] - это просто синтаксическое неудобство. Почему стандарт C поощрять это?


В стандарте C89 есть предел перевода для строковых литералов:

509 символов в литеральном литерале или в строковой литературе (после конкатенации)

Нет ограничений для массивов char; возможно

32767 байт в объекте (только в размещенной среде)

(я не уверен, что означает объект или размещенная среда), но во всяком случае это гораздо более высокий предел.

Я понимаю, что строковый литерал эквивалентен массиву char, содержащему символы, т.е. всегда можно переписать что-то вроде этого:

const char* str = "foo";

в этот

static const char __THE_LITERAL[] = { 'f', 'o', 'o', '\0' };
const char* str = __THE_LITERAL;

Итак, почему такой жесткий предел для литералов?

4b9b3361

Ответ 1

Ограничение на строковые литералы - это требование времени компиляции; существует аналогичный предел длины логической строки источника. Компилятор может использовать структуру данных фиксированного размера для хранения исходных строк и строковых литералов.

(C99 увеличивает эти конкретные пределы от 509 до 4095 символов.)

С другой стороны, объект (такой как массив char) может быть создан во время выполнения. Ограничения, скорее всего, навязываются архитектурой целевой машины, а не дизайном компилятора.

Обратите внимание, что это не верхние границы, наложенные на программы. Компилятор не обязан налагать какие-либо конечные пределы вообще. Если компилятор накладывает ограничение на длину строки, он должен быть не менее 509 или 4095 символов. (Большинство реальных компиляторов, я думаю, не налагают фиксированные ограничения, а динамически распределяют память динамически.)

Ответ 2

Это не то, что 509 символов является пределом для строки, это минимум, необходимый для совместимости с ANSI, как описано здесь.

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

Насколько количество символов действительно может быть в строковом литерале, это зависит от компилятора.

Вот несколько примеров:

  • MSVC: 2048
  • GCC: No Limit (до 100 000 символов), но дает предупреждение после 510 символов:

    Строковый литерал длиной 100000 превышает максимальную длину 509, что компиляторы C90 должны поддерживать

Ответ 3

Извините за поздний ответ, но я хотел бы проиллюстрировать разницу между этими двумя случаями (Ричард Дж. Росс уже указал, что они не эквивалентны.)

Предположим, вы попробуете это:

const char __THE_LITERAL[] = { 'f', 'o', 'o', '\0' };
const char* str = __THE_LITERAL;
char *str_writable = (char *) str;  // Not so const anymore
str_writable[0] = 'g';

Теперь str содержит "goo".

Но если вы это сделаете:

const char* str = "foo";
char *str_writable = (char *) str;
str_writable[0] = 'g';

Результат: segfault! (на моей платформе, по крайней мере.)

Вот принципиальное отличие: в первом случае у вас есть массив, который инициализируется "foo", но во втором случае у вас есть фактический строковый литерал.

На боковой ноте

const char __THE_LITERAL[] = { 'f', 'o', 'o', '\0' };

в точности эквивалентно

const char __THE_LITERAL[] = "foo";

Здесь = действует как инициализатор массива, а не как назначение. Это очень отличается от

const char *str = "foo";

где адрес строкового литерала присваивается str.