2011-09-28 5 views
9

これをGCC 4.6で試してみると、コンパイルとリンクが行われますが、実行時にMacOS上で「バスエラー」メッセージが表示されます。 VS2010はそれをコンパイルしません。これは正しいC++ 0xコードですか?

しかし、これは実際には標準のC++ 0xで動作するのでしょうか?

#include <cstdio> 
int (*main)()=[]()->int{printf("HEY!\n");return 0;}; 

はい、「メイン」をラムダ関数として定義することです。

+13

私はあなたがC++ 11の最新の最高の高度な機能を使いたいと思っていますが、まだ 'cstdio'と' printf'を使用しています:-) – paxdiablo

+4

@paxdiablo:printf rocks !!! I/OストリームでC++が失敗しました:) –

+1

Stroustroupによると、Cで足を撃つことができれば、C++は足を吹き飛ばすことができます!これは私が「マゾヒズム」と呼ぶものです! I/Oは、プロジェクト内のストリームおよびそれらに古いC IOシステムより遅い10〜20倍を見つけ、私は古いものに固執してきたみました後:-)) –

答えて

14

記号mainは関数ではなく、関数へのポインタであるため、これは有効なC++プログラムではありません。そのため、セグメント化エラーが発生します。実行時にポインタを実行しようとしています。

+0

1:(元の質問に私のずさんなコメントを削除し、ここで起こっていただきました並べ替えのより良い説明答えること。。) –

+0

その後、私はそれが正しいと、このコードを受け入れることを、実際にGCCのバグだと思いますか? – hasvn

+0

@ hasvn、わかりませんが、これは標準で診断が必要ない場合の1つだと思います。だから、gccは明らかかもしれません。 – avakar

3

いいえ、これは正しくありません。

メインは特別な関数であり、厳密な要件があります(通常の関数よりも厳密です)が、関数とは何か、そして関数のポインタとは何か混乱しています。

論理的な問題は、関数と、関数へのポインタを保持している変数(主にしたいもの)との間に違いがあることです。 関数はメモリ内の固定アドレスを持っているので、単にアドレスが呼び出される関数を呼び出すことができます。関数へのポインタをメモリ内のアドレスにポイントするので、ポインタが何を指しているのかを最初に読んでそのアドレスを呼び出すために必要な関数を呼び出すことができます。

関数へのポインタは、関数とは異なるレベルの間接参照を持っています。

構文は、ポインタの場合には(xあなたはx(42)を書くことができます関数へのポインタですが、xではなく、関数の場合、まだ生成されたマシンコードが異なる場合つまり...値と同じである必要がありますルックアップされ、呼び出しアドレスは実行時に決定され、アドレスは固定されている(再配置まで)。リンク時に決定される。

0

<cstdio>を#includeすると、printf()はstd :: printf()でなければなりません。そして無効なmain()についての他のもの。

+0

いいえ、 'cXXX'がグローバル名前空間への注入を含むかどうかは、標準では不明です。 'std ::'を使うのは_wise_ですが、 "must"はおそらく過剰です。 – paxdiablo

+0

これはとにかくハーフジョークでした。私はそれが移植性のために必要であることに注意するために答えを編集します。 (生き方のために移植可能なコードを書いている人は、このように考え始めます...) –

0

今、コンパイルするべきではありません。ラムダ式は型(ファンクタ)を生成します。 型から関数ポインタへの暗黙的な変換はありません。

コンパイラによっては、main関数はC++またはCリンケージ(実装定義)を持つことができます。ラムダ式は、関数呼び出し演算子を持つC++型を返します。したがって、C++リンケージです。

+0

実際には、キャプチャしていないラムダから関数ポインタへの暗黙の変換があります。 – avakar

+0

引用:(5.1.2/6)。 –

+0

あなたはどちらも正しいです。しかし、それは暗黙的にメンバー関数へのポインタに変換され、空き関数には変換されません。それを漠然と思い出して、私を混乱させたかもしれません。 – mloskot

関連する問題