2012-08-28 3 views
7

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

#include <cassert> 

void foo() {} 

void bar() {} 

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

答えて

7

折りたたみ同一のコードC++ 11標準は

(ポインタ変換後に)同じタイプの
ポインタは比較することができ5.10等価演算子と言い平等のために。同じ型の2つのポインタは、両方がnullの場合、同じ関数を指すポインタ、または両方が同じアドレス(3.9.2)を表す場合に限り、等しいと比較されます。

関数へのポインタがない場合、それらは同じアドレスを持つかもしれませんが、わかりません。 の場合、2つの異なる関数へのポインタを比較して、等しいとは比較してはいけません。混乱のため


一つの原因は、MSVCコンパイラが(intlongなど)さ​​まざまなタイプのため、同一のマシンコードを生成するために起こるテンプレート関数のコードを結合することが知られていることかもしれません。これは準拠していません。

しかし、これは異なるシグネチャの関数であり、正確にはこの質問に関するものではありません。

+0

最後のコメントは今や意味をなさない。異なる引数型の場合、異なる関数ポインタがあるため、同じ型の2つの[関数]ポインタに関する規則は適用されなくなります。 – MSalters

+0

それは本当です。異なる関数が同じアドレスを得ることができるが、本当に質問が何を求めているのではないか、 –

1

実装の詳細。

(C99,5.1.2.3p1) "この国際標準の意味論的記述は、最適化問題が無関係な抽象機械の動作を記述している。

+0

引用は空白です。質問は、抽象機械とは異なる実際のコンパイラについてですが、(最適化の存在下であっても)許容される抽象機械の1つと同じ観察可能な動作を示さなければならない。 – MSalters

3

はい。 C99 6.5.10:6

二つのポインタが比較等しい場合にのみ両方ヌルポインタがある場合、両方 は、オブジェクトへのポインタと サブオブジェクトを含む同じオブジェクトへのポインタ(あるその始まる)または機能、...

編集:段落の残りの部分、それはいくつかの重要性を持っていることが判明するので:

は、どちらも同じ配列 オブジェクトの最後の要素を超えたものへのポインタであり、1つは1つの配列オブジェクト の末尾を指すポインタで、もう1つは異なる配列オブジェクトの先頭へのポインタです アドレス空間の にある最初の配列オブジェクトの直後に起こります。私はそれから取る何

:間違ったオペランドに適用

  • 平等は、非常に多くの言葉では、指定されていません。それは間違った理由で偶然に当てはまるかもしれませんが、あなたが間違って使用すると、それが間違って使用されると、未定義ではありません。<は未定義です。
  • 私が理解している限りでは、関数はオブジェクトでも配列の要素でもないので、この段落の残りの部分は関数には適用されません。
+0

実装は、実際には同じ機能であることを保証してはいけませんか?つまり、コンパイラがこれを最適化するのはいいですが、言語仕様関数はコンパイル後のアセンブリ関数よりも私には違って見えます。 –

+0

Boの答えから、最後の部分は "または両方が同じアドレスを表します"。この見積もりの​​最後の部分は似ていますか? –

+0

@DanielSloof私はそれが '...'の後に来るものに依存すると思う。 –

2

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

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

ICFは:

関連する問題