web-dev-qa-db-ja.com

int(*)(int *)= 5(または任意の整数値)の意味

私はこれを理解できません:

_int main() {
    int (*) (int *) = 5;
    return 0;
}
_

上記の割り当ては、g ++ c ++ 11でコンパイルされます。 int (*) (int *)は、_(int *)_を引数として受け取り、intを返す関数へのポインタであることは知っていますが、どのようにそれを5に等しくすることができるかわかりません。常に5を返す関数(F#での最近の学習から、おそらく笑)、次に、簡単に、関数ポインターがメモリ位置5を指していると思いましたが、それは明らかに動作せず、16進数値も動作しません。

関数がintを返すためである可能性があり、intを割り当てることは(なんとか)大丈夫だと考えて、私もこれを試しました:

_int * (*) (int *) = my_ptr
_

ここで_my_ptr_は_int *_型であり、この2番目の関数ポインターと同じ型で、int型の最初の場合と同じです。これはコンパイルされません。 _my_ptr_の代わりに5または任意のint値を割り当てても、この関数ポインター用にコンパイルされません。

では、割り当てはどういう意味ですか?

更新1

ベストアンサーに示されているように、バグであることを確認しています。ただし、関数ポインターに割り当てる値に実際に何が起こるかがどうなるか、または割り当てで何が起こるかはまだわかりません。それについての(良い)説明は非常にありがたいです!問題の詳細については、以下の編集を参照してください。

編集1

Gccバージョン4.8.2を使用しています(Ubuntu 4.8.2で)

編集2

実際には、それをあらゆるものと同等にすることは、私のコンパイラーで機能します。 std :: string変数、またはdoubleを返す関数名と同等である場合でも機能します。

編集2.1

興味深いことに、ポインターではないデータ型を返す関数への関数ポインターにすると、次のようにコンパイルできます。

_std::string (*) () = 5.6;
_

しかし、関数ポインターがポインターを返す関数を指すとすぐに、次のようにコンパイルされません。

_some_data_type ** (*) () = any_value;
_
87
Konrad Kapp

これはg ++のバグです。

 int (*) (int *) 

型名です。

C++では、識別子のない型名を持つ宣言を持つことはできません。

したがって、これはg ++でコンパイルされます。

 int (*) (int *) = 5;

これもコンパイルします:

 int (*) (int *);

しかし、両方とも無効な宣言です。

[〜#〜] edit [〜#〜]

T.C。 コメントBugzillaのバグに言及 6068 同様のテストケース しかし、まだ承認されていません。バグはbugzillaで確認されています。

EDIT2

上記の2つの宣言がファイルスコープにある場合、g ++は診断を正しく発行します(ブロックスコープで診断を発行できません)。

EDIT3

G ++バージョン4(4.9.2)の最新リリース、最新のプレリリースバージョン5(5.0.1 20150412)、および最新の実験バージョン6(6.0.0 20150412)で問題を確認し、再現できます。

59
ouah

有効なC++ではありません。特定のコンパイラはたまたまコンパイルされるため、有効になりません。コンパイラは、すべての複雑なソフトウェアと同様に、バグがある場合があり、これはバグのようです。

対照的にclang++文句:

funnycast.cpp:3:11: error: expected expression
    int (*) (int *) = 5;
          ^
funnycast.cpp:3:18: error: expected '(' for function-style cast or type construction
    int (*) (int *) = 5;
             ~~~ ^
funnycast.cpp:3:19: error: expected expression
    int (*) (int *) = 5;
                  ^
3 errors generated.

問題のある行が有効なC++ではないため、これは予想される動作です。それは割り当てであると主張しています(=)が識別子を含みません。

27
Edward

他の回答が指摘しているように、それはバグです

int (*) (int *) = 5;

コンパイルします。意味を持つと予想されるこのステートメントの合理的な近似は次のとおりです。

int (*proc)(int*) = (int (*)(int*))(5);

procは、5を取り、intを返す関数のベースアドレスであるアドレスint*を期待する関数へのポインターです。

一部のマイクロコントローラ/マイクロプロセッサでは、5が有効なコードアドレスである場合があり、そのような関数をそこに配置できる場合があります。

ほとんどの汎用コンピューターでは、nullポインターアクセスをキャッチするために、メモリの最初のページ(4Kページのアドレス0-1023)は意図的に無効(マップされていない)です。

したがって、動作はプラットフォームに依存しますが、*procが呼び出されたときにページフォールトが発生すると合理的に予想できます(たとえば、(*proc)(&v))。 *procが呼び出される前に、異常なことは何も起こりません。

動的リンカーを作成しているのでなければ、アドレスを数値的に計算して、それらを関数へのポインター変数に割り当てるべきではありません。

9
Atsby
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/cc1plus.exe -da so.cpp

このコマンドラインは、多くの中間ファイルを生成します。最初のso.cpp.170r.expand、言う:

...
int main() ()
{
  int D.2229;
  int _1;

;;   basic block 2, loop depth 0
;;    pred:       ENTRY
  _1 = 0;
;;    succ:       3

;;   basic block 3, loop depth 0
;;    pred:       2
<L0>:
  return _1;
;;    succ:       EXIT

}
...

これはまだ正確に何が起こるかには答えませんが、正しい方向への一歩であるべきです。

2
Roland Illig