Вы не можете полагаться на идентичные строковые литералы, имеющие одно и то же место в памяти, это решение реализации. В проекте стандарта C99 говорится, что это не указано, являются ли одни и те же строковые литералы разными, из раздела 6.4.5
Строковые литералы:
Не указано, являются ли эти массивы отдельными при условии, что их элементы имеют соответствующие значения. Если программа пытается изменить такой массив, поведение не определено.
Для C ++ это описано в черновом стандартном разделе 2.14.5
Строковые литералы, в котором говорится:
Все ли строковые литералы различны (то есть хранятся в неперекрывающихся объектах) определяется реализацией. Эффект от попытки изменить строковый литерал не определен.
Компилятору разрешено объединять строковые литералы, но вы должны понимать, как это работает от компилятора к компилятору, поэтому это не будет переносимым и потенциально может измениться. Visual Studio включает параметр для объединения строковых литералов
В некоторых случаях идентичные строковые литералы могут быть объединены в пул для экономии места в исполняемом файле. При объединении строковых литералов компилятор заставляет все ссылки на конкретный строковый литерал указывать на одно и то же место в памяти, вместо того, чтобы иметь каждую ссылочную точку на отдельный экземпляр строкового литерала. Чтобы включить пул строк, используйте параметр компилятора / GF.
Обратите внимание, что это соответствует требованиям В некоторых случаях.
gcc
поддерживает объединение в пул и между модулями компиляции, и вы можете включить его с помощью - fmerge-константы:
Попытка объединить идентичные константы (строковые константы и константы с плавающей запятой) в единицах компиляции.
Этот параметр используется по умолчанию для оптимизированной компиляции, если ассемблер и компоновщик поддерживают его. Используйте -fno-merge-constants, чтобы запретить такое поведение.
обратите внимание, использование попытки и если ... поддерживает его.
Что касается обоснования, по крайней мере для C, не требующего объединения строковых литералов в пул, мы можем видеть из этого заархивировал обсуждение строковых литералов на comp.std.c, которое объяснялось широким разнообразием реализаций в то время:
GCC мог служить примером, но не мотивацией. Частично желание иметь строковые литералы в данных, преобразовываемых в ПЗУ, было связано с поддержкой, например, преобразования в ПЗУ. Я смутно припоминаю, что использовал пару реализаций C (до того, как было принято решение X3J11), где строковые литералы либо автоматически объединялись в пул, либо сохранялись в разделе программы с постоянными данными. Учитывая существующее разнообразие практик и доступность простого обходного решения, когда требуются исходные свойства UNIX, казалось лучше не пытаться гарантировать уникальность и возможность записи строковых литералов.
person
Shafik Yaghmour
schedule
09.10.2014
const
строками. - person Alnitak   schedule 09.10.2014char const[]
и является константным объектом. В C строковый литерал имеет типchar[]
. Но есть особые правила, согласно которым вы не можете его изменять, иначе это приведет к неопределенному поведению. - person James Kanze   schedule 09.10.2014const
, я считаю возможным (но может привести к неопределенному поведению) для программиста перезаписать содержимое строки, что, если оно объединено в пул, не сработает. - person Alnitak   schedule 09.10.2014static char buf[]
, чтобы принудительно иметь тот же адрес. Итак, с C ++ следующее может помочь Выравнивание статических строковых литералов (и вы можете забыть о выравнивании). - person Jarod42   schedule 09.10.2014