7

名前だけが異なる関数 (パラメーターや戻り値の型も異なる) が C と C++ で同じアドレスを共有できないという保証はありますか? 私はそれについて標準で何も見ていません。

#include <cassert>

void foo() {}

void bar() {}

int main()
{
    assert(foo != bar);
}
4

4 に答える 4

7

C++11標準は言う

5.10 等値演算子
(ポインタ変換後の) 同じ型のポインタは、等しいかどうかを比較できます。同じ型の 2 つのポインターは、両方が null であるか、両方が同じ関数を指しているか、または両方が同じアドレスを表している場合にのみ、等しいと比較されます (3.9.2)。

関数へのポインターがない場合は、同じアドレスを持っている可能性がありますが、わかりません。2 つの異なる関数へのポインターを比較する場合、それらが等しく比較されてはなりません。


混乱の原因の 1 つは、MSVC コンパイラがテンプレート関数のコードを組み合わせて、たまたま異なる型 (intと などlong) の同一のマシン コードを生成することが知られていることです。これは準拠していません。

ただし、これは異なるシグネチャを持つ関数のためのものであり、この質問の内容とは正確には異なります。

于 2012-08-28T20:52:19.480 に答える
3

はい。C99 6.5.10:6

2 つのポインターは、両方が null ポインターであり、両方が同じオブジェクト (オブジェクトへのポインターとその先頭のサブオブジェクトを含む) または関数へのポインターである場合にのみ、等しいと見なされます。</p>

編集:段落の残りの部分。重要性があることが判明したため:

両方が同じ配列オブジェクトの最後の要素の 1 つ後ろを指すポインターであるか、1 つが 1 つの配列オブジェクトの最後の要素を 1 つ過ぎたポインターであり、もう 1 つは最初の配列オブジェクトの直後にある別の配列オブジェクトの開始点を指すポインターです。アドレス空間の配列オブジェクト。

私がそれから得たもの:

  • 間違ったオペランドに適用される等価性は、非常に多くの言葉で指定されていません。無関係な理由で誤って真になる可能性がありますが、間違って使用しても未定義ではなく、間違って使用しても<未定義です。
  • 私の理解では、関数はオブジェクトでも配列の要素でもないため、残りの段落は関数には適用されません。
于 2012-08-28T20:48:30.667 に答える
2

最適化がオンになっている多くのコンパイラでは、2 つの関数が同じアドレスを持つようになります。たとえば、msdnから:

/OPT:ICFを使用すると、同じアドレスが別の関数に割り当てられたり、読み取り専用のデータ メンバー (/Gy でコンパイルされた const 変数) に割り当てられたりする可能性があります。そのため、/OPT:ICF は、関数のアドレスまたは読み取り専用データ メンバーが異なることに依存するプログラムを中断する可能性があります。詳細については、「/Gy (関数レベルのリンクを有効にする)」を参照してください。

ICF : 同一コードの折りたたみ

于 2012-08-28T20:49:39.690 に答える
1

実装の詳細。

(C99、5.1.2.3p1) 「この国際標準のセマンティック記述は、最適化の問題が無関係な抽象マシンの動作を記述しています。」

于 2012-08-28T20:47:30.993 に答える