В стандарте равенство обсуждается в §6.5.9 «Операторы равенства», &
обсуждается в §6.5.3.2 «Операторы адреса и косвенности», а const
обсуждается в §6.7.3 «Тип классификаторы». Соответствующий отрывок о равенстве указателей - §6.5.9.6:
Два указателя сравниваются равными тогда и только тогда, когда оба являются нулевыми указателями, оба являются указателями на
тот же объект (включая указатель на объект и подобъект в его начале) или функцию, [или указатели после конца массива]
Единственное определение &
состоит в том, что «унарный оператор &
выдает адрес своего операнда. […] Результатом является указатель на объект или функцию, обозначенный его операндом. »(§6.5.3.2.3). К сожалению, нет формального определения слова «адрес»; но разные объекты (для равенства, определенного ==
) имеют разные адреса, потому что адреса - это указатели, которые отличаются определением равенства выше.
Что касается значения const
, §6.7.3 не указывает, что const
имеет какое-либо отношение к тому, что делает объект (который является «областью хранения данных в среде выполнения, содержимое которой может представлять значения »согласно §3.14). Далее в сноске указывается, что «реализация не должна выделять память для такого объекта, если его адрес никогда не используется». Хотя это ненормативно, это сильный признак того, что если адрес используется, то для каждого объекта должно быть выделено хранилище .
Обратите внимание, что если объекты const volatile
, то совершенно ясно (насколько ясно может быть volatile
), что они не могут иметь один и тот же адрес, потому что объекты const volatile
изменяемы реализацией. (§6.7.3.10 имеет пример использования const volatile
.)
Даже в энергонезависимом случае const
указывает только на то, что этой части программы запрещено изменять объект, а не то, что объект доступен только для чтения в целом. Чтобы объединить хранилище объекта const
с чем-то другим, смелый разработчик должен был бы гарантировать, что ничто не сможет изменить объект. Это довольно сложно для объекта с внешней связью в реализации с отдельной компиляцией (но, конечно, мы уходим от стандарта и не попадаем на практическую территорию).
Если речь идет о написании программы на C, то вы можете увеличить свои шансы, задав объектам разные значения:
const int x = __LINE__;
const int y = __LINE__;
Если речь идет о теоретической модели C, я бы сделал объекты различимыми. Вам нужно будет обосновать этот выбор, суммируя ответы, приведенные здесь, в абзаце (расширенной версии) вашей статьи.
С другой стороны, если речь идет о написании оптимизирующего компилятора, я сомневаюсь, что многим реальным программам будет вредно объединять константы. Я бы пошел на слияние во встроенном компиляторе, где пользователи привыкли играть осторожно с крайними случаями, и где сохраненная память может быть ничтожной. Я бы пошел против слияния в размещенной платформе, где любой выигрыш был бы незначительным.
(Ссылки от N1256 a.k.a. C99 + TC3. Я не думаю, что версия имеет значение.)