Имеют ли разные функции разные адреса?

Рассмотрим эти две функции:

void foo() {}
void bar() {}

гарантировано ли, что &foo != &bar?

По аналогии,

template<class T> void foo() { }

гарантировано ли, что &foo<int> != &foo<double>?


Я знаю два компоновщика, которые объединяют эти определения функции fold.

MSVC агрессивно сворачивает функции COMDAT, поэтому две функции с одинаковой реализацией можно превратить в одну функцию. В качестве побочного эффекта две функции используют один и тот же адрес. У меня сложилось впечатление, что это незаконно, но я не могу найти, где в стандарте это сделано незаконно.

Компоновщик Gold также объединяет функции с параметрами safe и all. safe означает, что если адрес функции занят, он не складывается, а all складывается, даже если адрес занят. Таким образом, сгиб золота safe ведет себя так, как будто функции имеют разные адреса.

Хотя свертывание может быть неожиданным, и есть код, который использует разные (идентичные реализации) функции, имеющие разные адреса (поэтому сворачиваться может быть опасно), действительно ли это незаконно в соответствии с текущим стандартом C++? (С++ 14 на данный момент) (Естественно, как будто safe свертывание допустимо)


person Yakk - Adam Nevraumont    schedule 23.10.2014    source источник
comment
Интересно, может ли такая оптимизация/преобразование изменить видимый вывод кода. Тогда сам вопрос может быть преобразован. Если вывод может измениться, если это явно не разрешено, это незаконно. В противном случае это законно.   -  person luk32    schedule 23.10.2014
comment
Я не могу найти ничего в стандарте, определяющего разные адреса для функций. Это может просто означать, что я недостаточно внимательно искал.   -  person Mike Seymour    schedule 23.10.2014
comment
Я уверен, что видел этот вопрос раньше   -  person Lightness Races in Orbit    schedule 23.10.2014
comment
Связано: Почему две функции имеют одинаковый адрес?   -  person Nawaz    schedule 23.10.2014
comment
Золотой линкер имеет: --icf [none,all,safe] Identical Code Folding. '--icf=safe' Folds ctors, dtors and functions whose pointers are definitely not taken.   -  person Marc Glisse    schedule 24.10.2014
comment
@Marc nod -- насколько я знаю, у золота и MSVC есть такая сворачиваемость, но у MSVC нет настройки safe. На самом деле, вы всегда можете сбросить карты, за исключением случаев, когда вы просите адрес, который может создать дополнительные копии (или использовать таблицу переходов). Мне интересно, является ли MSVC технически законным.   -  person Yakk - Adam Nevraumont    schedule 24.10.2014
comment
@Yakk gold имеет настройку safe, потому что они знают, что all является незаконным ( research.google.com/pubs/ pub36912.html). Но я не хочу участвовать в этом судебном споре.   -  person Marc Glisse    schedule 24.10.2014
comment
@MarcGlisse: Престижность за обнаружение этого, только одно наблюдение: они никогда не говорят, что разрешено полагаться на любые две функции, имеющие разные адреса. Цитата: Однако ICF может быть небезопасным, поскольку он может изменить поведение во время выполнения кода, который зависит от того, что каждая функция имеет уникальный адрес.   -  person Deduplicator    schedule 24.10.2014
comment
@MarcGlisse Я вставил вашу ссылку на эту золотую бумагу в исходный пост.   -  person Yakk - Adam Nevraumont    schedule 24.10.2014
comment
@LightnessRacesinOrbit: Да, вы видели это раньше: stackoverflow.com/q/14188612, хотя и с меньшим количеством голосов, ответов и споров. ;-)   -  person Deduplicator    schedule 12.11.2014
comment
@Deduplicator: Ха, поехали   -  person Lightness Races in Orbit    schedule 12.11.2014
comment
Тогда это не обман?   -  person Lightness Races in Orbit    schedule 12.11.2014
comment
@легкость, да. Есть ли способ перенести ответы? Я оставил этот пункт неотмеченным, поскольку в настоящее время стандарт кажется неоднозначным. Если мы не можем мигрировать, должны ли мы обманывать свои ответы на ваши или ваши на мои (нарушение причинно-следственной связи!), чтобы сохранить интересные ответы? (проверенный ответ на ваш кажется описанным ниже).   -  person Yakk - Adam Nevraumont    schedule 12.11.2014
comment
@Yakk: Моды при некоторых обстоятельствах объединяют дубликаты. Насколько эти двое достаточно близки для этого, я не уверен. У вас здесь есть несколько хороших ответов, так что я просто изменю свой на ваш.   -  person Lightness Races in Orbit    schedule 12.11.2014
comment
@LightnessRacesinOrbit какой-либо флаг для слияния? Из моего опыта со слияниями это кажется разумным, ответ на ваш вопрос определенно очень хорошо подходит здесь.   -  person Shafik Yaghmour    schedule 15.11.2014
comment
Связано с: Правильно ли Visual Studio 2013 оптимизируется при наличии /OPT:ICF?.   -  person Shafik Yaghmour    schedule 16.03.2015
comment
@ShafikYaghmour несколько - в этом вопросе функции одинаковы только потому, что два адреса const данных, которые логически различны, объединяются в один: в стандарте очень ясно, что разные объекты имеют разные адреса, так что это незаконно. Только после этого недопустимого свертывания реализации двух функций становятся одинаковыми, и ICF на уровне функций приводит к тому, что две функции имеют одно и то же значение. Этот вопрос является допустимым на функциональном уровне.   -  person Yakk - Adam Nevraumont    schedule 18.03.2015
comment
@Yakk, конечно, кажется, что они могут быть частью одной и той же проблемы оптимизации, поэтому я упомянул об этом. Это не идентичные проблемы.   -  person Shafik Yaghmour    schedule 18.03.2015
comment
Смотрите мое обновление, Ян Хубичка согласен с @MarcGlisse, и, оглядываясь назад, я теперь вижу это по-другому, и это имеет смысл, что это не соответствующее поведение.   -  person Shafik Yaghmour    schedule 14.04.2015


Ответы (4)


5.10 Операторы равенства [expr.eq]

1 Операторы == (равно) и != (не равно) группируются слева направо. Операнды должны иметь арифметику, перечисление, указатель или указатель на тип члена или тип std::nullptr_t. Оба оператора == и != дают true или false, т. е. результат типа bool. В каждом из приведенных ниже случаев операнды должны иметь один и тот же тип после применения указанных преобразований.
2 Если хотя бы один из операндов является указателем, преобразования указателя (4.10) и квалификационные преобразования (4.4) выполняются для обоих операндов, чтобы привести их к составному типу указателя (раздел 5). Сравнение указателей определяется следующим образом: Два указателя считаются равными, если они оба равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес (3.9.2), в противном случае они сравниваются неравно.

Давайте возьмем последний бит за битом:

  1. Два пустых указателя сравниваются равными.
    Хорошо для вашего здравомыслия.
  2. Два указателя на одну и ту же функцию сравниваются равными.
    Все остальное было бы чрезвычайно удивительно.
    Это также означает, что только одна внешняя версия любой inline-функции может иметь свой адрес, если только вы не хотите сделать сравнения указателей функций непомерно сложными и дорогими.
  3. Оба представляют один и тот же адрес.
    Теперь все дело в этом. Отбросив это и сведя if and only if к простому if, мы оставим это на усмотрение, но это явное требование сделать любые две функции идентичными, если это не меняет наблюдаемое поведение соответствующей программы.
person Deduplicator    schedule 23.10.2014

Это выглядит как отчет о дефекте 1400: Функция равенство указателей решает эту проблему и, как мне кажется, говорит о том, что эту оптимизацию можно делать, но, как показывают комментарии, существуют разногласия. В нем говорится (выделено мной):

Согласно 5.10 [expr.eq], параграф 2, два указателя на функцию сравниваются как равные, только если они указывают на одну и ту же функцию. Однако в качестве оптимизации реализации в настоящее время используют псевдонимы функций, которые имеют идентичные определения. Неясно, должен ли Стандарт явно учитывать эту оптимизацию или нет.

и ответ был:

Стандарт четко определяет требования, и реализации можно оптимизировать в рамках ограничений правила «как если бы».

Вопрос касается двух вопросов:

  • Можно ли считать эти указатели равными
  • Можно ли объединить функции

Основываясь на комментариях, я вижу две интерпретации ответа:

  1. Эта оптимизация в порядке, стандарт дает реализацию этой свободы в соответствии с правилом «как если бы». Правило как если бы описано в разделе 1.9 и означает, что реализация должна эмулировать только наблюдаемое поведение в соответствии с требованиями стандарта. Это все еще моя интерпретация ответа.

  2. Проблема полностью игнорируется, и в заявлении просто говорится, что корректировка стандарта не требуется, потому что очевидно, что правила «как если бы» охватывают это, но интерпретация предоставляется читателю в качестве упражнения. Хотя я признаю, что из-за краткости ответа я не могу отвергнуть эту точку зрения, в конечном итоге это совершенно бесполезный ответ. Это также кажется несовместимым с ответами в других NAD проблемах, которые, насколько я могу судить, указывают на проблему, если она существует.

Что говорится в проекте стандарта

Поскольку мы знаем, что имеем дело с правилом как если бы, мы можем начать с него и отметить, что в разделе 1.8 говорится:

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

и примечание 4 говорит:

В соответствии с правилом «как если бы» реализации разрешается хранить два объекта по одному и тому же машинному адресу или вообще не сохранять объект, если программа не может заметить разницу.

но примечание из этого раздела гласит:

Функция не является объектом, независимо от того, занимает ли она память так же, как объекты.

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

Далее идет раздел 5.10 Операторы равенства, в котором говорится (выделено мной):

[...] Два указателя сравниваются равными, если они оба равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес (3.9.2), в противном случае они сравниваются неравными.

который говорит нам, что два указателя равны, если они:

  • Нулевые указатели
  • Укажите на ту же функцию
  • Представлять тот же адрес

или оба представляют один и тот же адрес, по-видимому, дают достаточно свободы, чтобы позволить компилятору использовать псевдонимы для двух разных функций и не требуют указателей на разные функции для сравнения неравных.

Наблюдения

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

Если программа выводит результат &foo == &bar, это наблюдаемое поведение; рассматриваемая оптимизация изменяет наблюдаемое поведение.

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

а также:

[...] рассмотрим программу, которая определяет пустую функцию и использует их адреса как уникальные значения (подумайте о SIG_DFL, SIG_ERR и SIG_IGN в ‹signal.h› / ‹csignal›). Присвоение им одного и того же адреса приведет к поломке такой программы.

Как я отметил в своем комментарии, стандарт C требует, чтобы эти макросы генерировали различные значения из 7.14 в C11:

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

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

Обновить

Ян Хубичка, gcc разработчик, написал сообщение в блоге Связать время и интер- улучшения процедурной оптимизации в GCC 5, свертывание кода было одной из многих тем, которые он затронул.

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

Это не соответствует тому, чтобы две функции имели один и тот же адрес, поэтому MSVC здесь довольно агрессивен. Это, например, ломает сам GCC, потому что, к моему удивлению, сравнение адресов выполняется в предварительно скомпилированном коде заголовков. Он работает для многих других проектов, включая Firefox.

Оглядываясь назад, после нескольких месяцев чтения отчетов о дефектах и ​​размышлений о проблемах оптимизации, я склоняюсь к более консервативному чтению ответа комитета. Получение адреса функции является наблюдаемым поведением, поэтому свертывание идентичных функций нарушит правило как если бы.

Обновление 2

Также см. это обсуждение llvm-dev: Равенство указателя функции нулевой длины< /а>:

Это хорошо известная ошибка, нарушающая соответствие в link.exe; LLVM не должен усугублять ситуацию, вводя аналогичную ошибку. Более умные компоновщики (например, я думаю, что и lld, и gold) будут выполнять идентичное комбинирование функций только в том случае, если все функциональные символы, кроме одного, используются только в качестве цели вызовов (а не для фактического наблюдения за адресом). И да, это несоответствующее поведение (редко) ломает ситуацию на практике. См. этот исследовательский документ.

person Shafik Yaghmour    schedule 23.10.2014
comment
близко, но не совсем: для двух разных функций разрешено использовать один и тот же двоичный код (как если бы), но может быть недопустимо, чтобы адреса двух разных функций сравнивались и были равны. Один из способов приблизиться к этому — потребовать заглушки noops или jmps в начале функции, чтобы каждая из них получала разные адреса, но одно и то же тело (как я полагаю, некоторые эквиваленты складывания COMDAT, отличные от MSVC), - person Yakk - Adam Nevraumont; 23.10.2014
comment
@Yakk: для них не требуется сравнивать неравные. Если есть, цитируйте. - person Deduplicator; 23.10.2014
comment
@Yakk, возможно, я немного упускаю здесь, как вы понимаете термин псевдоним по отношению к указателям на функции? - person Shafik Yaghmour; 23.10.2014
comment
@Shafik Я говорю, что разрешение отчета о дефектах, похоже, говорит об оптимизации, при которой две функции имеют одно и то же тело, но когда вы берете указатели на них, вы получаете разные значения. Это явно не охватывает случай, о котором идет речь в моем вопросе. - person Yakk - Adam Nevraumont; 24.10.2014
comment
@Deduplicator Если прочитать это предложение таким образом (вы можете сказать, что две разные функции имеют одинаковый адрес), это означает, что нет требования, чтобы любые два указателя на функцию сравнивались неравно. Компилятор может превратить fptra == fptrb в !fptra == !fptrb (т. е. все ненулевые указатели функций эквивалентны). Это кажется странным. - person Yakk - Adam Nevraumont; 24.10.2014
comment
@Yakk, как и в случае с большинством отчетов о дефектах, ответ комитета действительно краток, я вижу вашу позицию, но я определенно не согласен, давайте посмотрим, придет ли кто-нибудь с более определенными знаниями. - person Shafik Yaghmour; 24.10.2014
comment
@Yakk: Это будет противоречить общему определению address, которое действует, если в стандарте нет другого определения. - person Deduplicator; 24.10.2014
comment
Я нахожу ответ комитета не просто кратким, но и непрозрачным. В примечании к стандарту говорится, что реализация может игнорировать любое требование этого международного стандарта, если результат как если бы требование было соблюдено, насколько это можно определить по наблюдаемому поведению. программы. Если программа выводит результат &foo == &bar, это наблюдаемое поведение; рассматриваемая оптимизация изменяет наблюдаемое поведение. Мое прочтение ответа состоит в том, что указатели должны сравниваться неравномерно, но я подозреваю, что это не то, что имелось в виду. - person Keith Thompson; 24.10.2014
comment
@KeithThompson, это хороший момент, я добавил ваше наблюдение к своему ответу, пожалуйста, дайте мне знать, если я неправильно понял. - person Shafik Yaghmour; 24.10.2014
comment
@ShafikYaghmour: у меня нет проблем с обновлением. На мой взгляд, поскольку они являются отдельными функциями в абстрактной машине, они являются отдельными функциями в том, что касается оператора "==" в их адресах. Я бы не возражал против того, чтобы адреса были равными, но, ИМХО, это потребовало бы изменения формулировки стандарта, а не просто заявления комитета о том, что стандарт уже достаточно ясен. - person Keith Thompson; 24.10.2014
comment
@KeithThompson, можете ли вы уточнить: поскольку они являются отдельными функциями в абстрактной машине, они являются отдельными функциями в том, что касается оператора ==, какая часть стандарта охватывает это, или это концептуальная идея, которая подразумевается, но не является явным? Йоханес имел в виду что-то подобное, но удалил комментарий и решил не продолжать. - person Shafik Yaghmour; 24.10.2014
comment
В ответе говорится, что это разрешено правилом «как если бы». Нет, это просто не так. В нем говорится, что оптимизация действительна, если разрешена правилом «как если», и недействительна, если не разрешена правилом «как если», без указания на то, разрешает ли правило «как если» эту конкретную оптимизацию. - person ; 24.10.2014
comment
@hvd, это не несправедливая интерпретация (как я уже упоминал, она краткая). Я просто нахожу это невероятно глупым и совершенно бесполезным ответом, если оптимизация действительно недействительна. Позвольте мне подумать о перефразировании моего ответа, я не вернусь в Интернет немедленно. Это не меняет моего убеждения в том, что это действительно, как я сказал с наблюдением Кита, это действительно меняет наблюдаемое поведение, но нет требований, чтобы указатели сравнивались неравно, если бы мы могли найти это требование, оптимизация явно была бы недействительной. - person Shafik Yaghmour; 24.10.2014
comment
@ShafikYaghmour: Это не явно, но я считаю это здравым смыслом. Очевидно, другие не согласны. Вопрос в том, могут ли две четко определенные функции быть одной и той же функцией. Может ли оптимизирующий компилятор, использующий общий код для двух функций, сделать их одной и той же функцией, видимой для пользовательского кода? Может ли он сделать то же самое для отдельных объектов? На практике рассмотрим программу, которая определяет пустую функцию и использует их адреса как уникальные значения (подумайте о SIG_DFL, SIG_ERR и SIG_IGN в <signal.h>/<csignal>). Назначение им одного и того же адреса приведет к поломке такой программы. - person Keith Thompson; 24.10.2014
comment
@KeithThompson интересный момент, который дает мне пищу для размышлений. Хотя обратите внимание, что в этом случае стандарт требует Определенные макросы ... которые расширяются до постоянных выражений с различными значениями из раздела 7.14 C11 и C99, и поэтому их псевдонимы определенно нарушат as -если правило. - person Shafik Yaghmour; 24.10.2014
comment
@KeithThompson: Казалось бы, ваша интерпретация позволит объединить функцию с отдельными, но идентичными функциями, чей адрес не занят, но каждая функция, адрес которой взят, может быть объединена только в том случае, если их адреса сравнивать как разные (в архитектуре, где указатели имеют больше битов, чем аппаратные адреса, два указателя могут представлять один и тот же физический адрес, но все же отображаться как разные). Если намерение состоит в том, что функции, чей адрес взят, должны давать разные адреса, интересно, почему это не говорит так? - person supercat; 04.01.2015
comment
@KeithThompson: также обратите внимание, что оптимизирующий компилятор может совместно использовать код для двух тела функций, но при этом давать им разные адреса. Адрес одной функции является началом тела, а адрес одной функции указывает на NOP непосредственно перед телом функции. Конечно, это усложняет связывание. - person Mooing Duck; 14.04.2015
comment
@MooingDuck: Другая возможность заключается в том, что реализация может использовать приемы отображения памяти, чтобы несколько страниц памяти указывали на одну и ту же физическую оперативную память, содержащую код. Я не знаю ни одной настольной системы, которая могла бы делать такие вещи, но такие хаки вряд ли неизвестны в мире встраиваемых систем. - person supercat; 17.04.2015
comment
@KeithThompson: Ну, вопрос в том, действительно ли это программа или компилятор сломаны, и я все еще склоняюсь к первому. Реализация, очевидно, может иметь дополнительную магию для тех символов, которые вы назвали... +Shafik: Что касается цитаты Яна Губички, он может просто ошибаться. Теперь, если бы он мог доказать это главой и стихом... В любом случае, я не думаю, что MS со своей стороны захочет, чтобы это складывание было объявлено вне закона, это сделало бы их либо менее конформными, либо менее эффективными, ни то, ни другое они не приветствуют. - person Deduplicator; 17.04.2016
comment
Изучив записи CWG по проблеме 1400, я почти уверен, что они имели в виду, что агрессивная версия оптимизации недействительна. - person T.C.; 29.01.2018
comment
@Т.С. согласился, и это то, что я пришел к выводу в конце. - person Shafik Yaghmour; 29.01.2018

да. Из стандарта (§5.10/1): «Два указателя одного и того же типа сравниваются равными тогда и только тогда, когда они оба равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес»

После создания экземпляров foo<int> и foo<double> становятся двумя разными функциями, поэтому сказанное выше относится и к ним.

person James Kanze    schedule 23.10.2014
comment
Это не мешает им представлять один и тот же адрес, но указывать на разные функции. - person Mike Seymour; 23.10.2014
comment
оба указывают на одну и ту же функцию или оба представляют один и тот же адрес Звучит запутанно... и запутанно. Как можно определить равенство с точки зрения одного и того же адреса? Я имею в виду, что здесь означает то же самое? равны, не так ли? Кроме того, здесь не говорится, что две разные функции должны иметь разные/неравные адреса. - person Nawaz; 23.10.2014
comment
@MikeSeymour: Как это не так? В заявлении ясно сказано, что если они указывают на разные функции, то указатели не могут сравниваться равными. - person Lightness Races in Orbit; 23.10.2014
comment
@LightnessRacesinOrbit: Нет, не так. Использование или означает, что они будут сравниваться как равные, если они представляют один и тот же адрес, но не указывают оба на одну и ту же функцию. - person Mike Seymour; 23.10.2014
comment
@MikeSeymour: я строго интерпретирую это как тот же адрес объекта. Фраза охватывает три режима значений указателя. Если это так, я бы посчитал это редакционным недочетом. В противном случае это довольно бессмысленно. - person Lightness Races in Orbit; 23.10.2014
comment
Гарантируется ли, что foo<int> и foo<double> являются разными функциями, если они не зависят от аргумента шаблона? - person luk32; 23.10.2014
comment
(ptra==ptrb) iff ( ( ptra равно null AND ptrb равно null) ИЛИ (ptra и ptrb оба относятся к одной и той же функции) ИЛИ ( ptra и ptrb оба относятся к одному и тому же адресу). Это означает, что если ptra и ptrb относятся к разным адрес но одна и та же функция, они должны сравниваться как равные (что бы это ни значило). Что означает address в стандарте? X тогда и только тогда (A или B или C) не совпадает с X тогда и только тогда, когда B. Однако , если мы можем исключить A или C как возможные, то да. - person Yakk - Adam Nevraumont; 23.10.2014
comment
@Nawaz тот же адрес актуален для объектов, где представление объекта требует, чтобы они имели адрес. И это формулировка ласки, чтобы избежать проблемы, когда единица после конца массива в конечном итоге указывает на другой объект. Здесь оба указывают на одну и ту же функцию. - person James Kanze; 23.10.2014
comment
@MikeSeymour Функции не имеют адресов (по стандарту). - person James Kanze; 23.10.2014
comment
@JamesKanze: Я бы хотел сказать это. На самом деле я имею в виду, что я хотел бы быть в состоянии доказать это. - person Lightness Races in Orbit; 23.10.2014
comment
@LightnessRacesinOrbit Вы на правильном пути. В C++ только объекты имеют адреса. У вас может быть указатель на функцию, но это не адрес. - person James Kanze; 23.10.2014
comment
@JamesKanze: Кроме тех случаев, когда они это делают. См., например, 13.4, Адрес перегруженной функции. - person Mike Seymour; 23.10.2014
comment
@LightnessRacesinOrbit Вы не найдете утверждения, что у функций нет адресов. Однако память занимают только объекты, и только вещи, занимающие память, могут иметь адреса. См. также §5.3.1/3; унарный оператор & функции возвращает указатель, а не ее адрес (в отличие от объектов). - person James Kanze; 23.10.2014
comment
@ luk32 Это, безусловно, цель. Каждый экземпляр создает новую функцию. (Мы обсуждали это в комитете. Присутствовал представитель Microsoft.) - person James Kanze; 23.10.2014
comment
Я немного скептичен, кажется, что фраза или оба представляют один и тот же адрес позволяет увидеть оптимизацию. Возможно, это не было намерением, но я мог видеть, как это могло быть прочитано таким образом. - person Shafik Yaghmour; 23.10.2014
comment
@Yakk См. §1.8/6, в котором определяется адрес объекта. Нигде нет ничего об адресе функции, по крайней мере, что я могу найти; есть указатели на функции, но указатель на функцию — это всего лишь указатель; это не адрес, а все, что компилятор хочет разрешить найти функцию. - person James Kanze; 23.10.2014
comment
@JamesKanze: у вас нет такой хорошей цитаты о том, что означает адрес функции, но это не дает вам права просто игнорировать ее. - person Deduplicator; 23.10.2014
comment
@MikeSeymour Интересное название; адрес слова никогда не появляется в разделе. Я не думаю, что имена разделов являются нормативными (они ничего не определяют), но кажется, что имя выбрано небрежно, учитывая остальную часть стандарта, включая содержимое этого раздела. - person James Kanze; 23.10.2014
comment
@Deduplicator Стандарт определяет все используемые в нем термины. Что касается стандарта, то, несмотря на небрежную формулировку заголовка одного раздела (в котором слово адрес используется в его обыденном смысле, а не в том смысле, в котором его использует стандарт), функции просто не имеют адресов. - person James Kanze; 23.10.2014
comment
Вы знаете, вполне логично, чтобы присутствовали все три варианта; они разные и только вместе дают все гарантии, которые хотелось бы (и не мало). - person Deduplicator; 23.10.2014
comment
Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат. - person Taryn; 23.10.2014
comment
@Deduplicator: заголовок раздела, очевидно, должен быть унарным и функциями-членами, потому что официально унарный оператор & в C ++ не называется оператором адреса ... но заголовок раздела на самом деле относится к оператору. адрес в названии этого раздела является неделимой фразой. - person Ben Voigt; 26.04.2021

Таким образом, проблематичной частью явно является фраза или оба представляют один и тот же адрес (3.9.2).

IMO, эта часть явно предназначена для определения семантики типов указателей объектов. И только для типов указателей объектов.

Фраза ссылается на раздел 3.9.2, что означает, что мы должны смотреть туда. 3.9.2 рассказывает (среди прочего) об адресах, которые представляют указатели объектов. Он не говорит об адресах, которые представляют указатели функций. Что, ИМО, оставляет только две возможные интерпретации:

1) Фраза просто не применима к указателям на функции. Таким образом, остаются только два нулевых указателя и два указателя на одну и ту же функцию, которые сравниваются равными, чего, вероятно, и ожидало большинство из нас.

2) Фраза действительно применима. Поскольку это относится к 3.9.2, в котором ничего не говорится об адресах, представляемых указателями функций, мы можем сделать любые два указателя функций равными для сравнения. Что очень неожиданно и, конечно, делает сравнение указателей на функции совершенно бесполезным.

Таким образом, хотя технически можно утверждать, что (2) является действительной интерпретацией, ИМО это не содержательная интерпретация, и поэтому ее следует игнорировать. И поскольку не все, кажется, согласны с этим, я также думаю, что необходимо уточнение в стандарте.

person Paul Groke    schedule 24.10.2014