Ответ 1
В стандарте, равенство обсуждается в п. 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.4). Кроме того, сноска указывает, что "для реализации не требуется выделять хранилище для такого объекта, если его адрес никогда не используется". Хотя это ненормативно, это убедительное указание, что если адрес используется, то для каждого объекта должно быть выделено хранилище.
Обратите внимание, что если объекты 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. Я не думаю, что версия имеет значение.)