Почему максимальная длина строкового литерала 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;
Итак, почему такой жесткий предел для литералов?
Ответы
Ответ 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
.