Intereting Posts
Замены GNU / Linux для функций Turbo C `clrscr` и` cprintf` Как сравнить длинные удвоения с qsort и с точки зрения NaN? C и реализация семафора низкого уровня Как выполнить exec () в фоновом режиме в C? Почему SCHAR_MIN определяется как -127 в C99? Преобразовать символ с большого конца в маленький endian в C Биты разрешения разделяемой памяти в системе V: значение и способы изменения Почему нельзя использовать указатель указателя в качестве параметра для объявления функции приема указателя массива Пользовательский распределитель памяти / менеджер в C? какой подход? Элемент доступа за пределами массива в C Почему C так быстро, и почему другие языки не такие быстрые или быстрые? LCC: Вперед декларация Typedef’d Enum Fail? «Реверсировать» набор макросов препроцессора C легко Лучшие практики, чтобы избежать проблем с указателями Инициализация classа с помощью malloc

В C, константные переменные гарантированно различаются по памяти?

Говоря о строковых литералах, в стандарте C99 говорится (6.4.5.6):

Не указано, являются ли эти массивы различными, если их элементы имеют соответствующие значения. Если программа пытается изменить такой массив, поведение не определено.

Я не мог найти ни одного подобного предупреждения или явной гарантии для константных переменных. Может ли выражение &x == &y в контексте const int x=12; const int y=12; const int x=12; const int y=12; оценить 1 ? Что относительно константной переменной и строкового литерала (т. &x == "\014\000\000" гарантированно будет 0 даже на 32-битной платформе с маленьким шрифтом)?

Для чего это стоит, раздел «Строковые литералы» в этом сообщении в блоге дает контекст вопроса.

В стандарте, равенство обсуждается в п. 6.5.9 «Операторы равенства», & обсуждается в п. 6.5.3.2 «Операторы адреса и косвенности», а const обсуждается в п. 6.7.3 «Типовые classификаторы». Соответствующий отрывок о равенстве указателя равен §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 aka C99 + TC3. Я не думаю, что версия имеет значение.)

Насколько мне известно, Стандарт не позволяет двум именованным объектам любого типа иметь один и тот же адрес (кроме членов объединения). Из пункта 6.5.9 / 6:

Два указателя сравнивают одинаковые, если и только если оба являются нулевыми указателями, оба являются указателями на один и тот же объект …

Строковые литералы не являются константными переменными, поэтому ваш вторичный вопрос является спорным, и я не вижу, что с ним связано 32-битность и сущность.

В

 const int x=12; const int y=12; 

x и y – разные переменные (как const-qual), так и разные адреса.

То же самое для другого примера.

Обратите внимание, что const является квалификатором для объекта. Что касается макета памяти, это не имеет значения, если он есть или нет.

6.4.5 / 6 говорит о массивах, соответствующих строковым литералам:

Неясно, являются ли эти массивы различными, если их элементы имеют соответствующие значения.

Так что это специальное правило, позволяющее сгруппировать строковые литералы. Я ничего не знаю в стандарте, который говорит то же самое для других объектов.