Стандарт не гарантирует, что адреса строковых литералов с одинаковым содержимым будут одинаковыми.Фактически, [lex.string] / 16 говорит:
Все ли строковые литералы различны (то есть хранятся ли в неперекрывающихся объектах) и являются ли последовательные вычисления строковый литерал выдают тот же или другой объект не указан.
Во второй части даже сказано, что вы не можете получить тот же адрес, когда функция, содержащая строковый литерал, называется второйвремя!Хотя я никогда не видел, чтобы компилятор делал это.
Так что использование одного и того же объекта массива символов при повторении строкового литерала является дополнительной оптимизацией компилятора.Установив флаги g ++ и флаги компилятора по умолчанию, я также обнаружил, что получаю один и тот же адрес для двух одинаковых строковых литералов в одном и том же модуле перевода.Но, как вы уже догадались, я получаю разные, если одно и то же содержимое строкового литерала появляется в разных единицах перевода.
Связанный интересный момент: для разных строковых литералов также разрешено использовать перекрывающиеся массивы.То есть, учитывая, что
const char* abcdef = "abcdef";
const char* def = "def";
const char* def0gh = "def\0gh";
возможно, вы обнаружите, что abcdef+3
, def
и def0gh
- это все один и тот же указатель.
Кроме того, это правило о повторном использовании или перекрытииСтроковые литеральные объекты применяются только к безымянному объекту массива, непосредственно связанному с литералом, который используется, если литерал немедленно затухает в указателе или связан со ссылкой на массив.Литерал также может использоваться для инициализации именованного массива, как в
const char a1[] = "XYZ";
const char a2[] = "XYZ";
const char a3[] = "Z";
Здесь объекты массива a1
, a2
и a3
инициализируются с использованием литерала, но считаются отличными отфактическое литеральное хранилище (если такое хранилище вообще существует) и следуйте обычным правилам объекта, поэтому хранилище для этих массивов не будет перекрываться.