6

ほとんどの C++ コンパイラはアセンブリで記述されていると思います。これにより、それらは完全に異なる言語になります(私は間違っている可能性があります)。そうは言ってもcout、単純な古い C のスタイル関数を作成するとしたら、どうすればよいでしょうか? coutたとえば、次のスニペットを使用すると、非常に印象的な機能がいくつかあります。

// endl not only prints a new line but also flushes the stream
cout << "Hello World!" << endl;

これは、Cでこれに変換されると確信しています:

printf("Hello World!\n");
fflush(1);                  //stdout = 1

ビジネスの次の順序、<<オペレーター。C++ ではこれは簡単ですが (演算子のオーバーロード)、C でこれを行う単一の方法は考えられません。

4

3 に答える 3

8

「<<」演算子構文と「operator<<」関数構文の間で変換すると、これについて考えるのに役立つ場合があります。C++ の例は、次の C++ コードと同等です。

operator<< ( operator<< (cout, "Hello World!"), endl);

ここで最初に気付くべきことは、実際には cout にはあまり賢さがないということです。賢いのは operator<< 関数です。具体的には、最初の引数としてストリーム オブジェクト (これは cout ですが、他の多くのものもそうです) を取る operator<< 関数のバージョンです。または、より正確には、最初の引数としてストリーム オブジェクトを取り、2 番目の引数として特定のものを取る operator<< 関数の範囲 - cout ストリームに入れることができるオブジェクトの種類ごとに 1 つあります。この構文にも C++ のトリックの 1 つが見られます。ストリーム オブジェクトの operator<< 関数は、常に指定されたストリーム オブジェクトを返すため、この性質の連鎖が可能になります。

C に似た関数構文を期待するリンカとシステム ABI に C++ コードを配置するために、ほとんどの C++ コンパイラは、関数名を「マングル」して、関数が持つ引数の型をコード化します。(もちろん、"<<" は有効な C のような関数名ではありません。) したがって、この関数のビットに対して生成されたアセンブリを見ると、2 つの関数の名前が次のようになっていることがわかります。互いに異なります -- 引数の型を示すサフィックスが付きます。そのようなことを手動で行うことができます:

operator_lshift__stream__endl(
  operator_lshift__stream__string(cout, "Hello World!"), endl);

そして、C で実装できるものがあります。

于 2009-08-10T05:29:06.697 に答える
5

そうです、C には演算子のオーバーロードがないため、<< 演算子の動作を変更することはできません。常にビット シフトを行うため、C++ にある正確なセマンティクスで 'cout' を記述する方法はありません。 C.

興味深いことに、g++ (GNU C++ コンパイラ) はほとんどが C で書かれています。

于 2009-08-10T04:40:56.573 に答える
4

C は実際には C++ コンパイラと標準ライブラリの一般的な実装言語です (実際には C++ 自体もそうです -- セルフホスティングまたは言語のブートストラップとして知られる概念です)。リッチで複雑な C++ 標準のソース全体を調べることができます。ライブラリ (および拡張機能)はここにあります(申し訳ありませんが、これは gcc 3 です。オンラインで簡単に参照できる gcc 4 ソース ツリーは見つかりませんが、もちろん、これらのソースを簡単にダウンロードしてローカル マシンで調べることができます)。

個人的には、代わりにこの本などの優れた本から始めることをお勧めします。C++ の iostream のあいまいな隅々まで (おまけとして、この本はまた、ロケールを巡るガイド付きツアーにも連れて行ってくれます -- 帽子をかぶってください!-)。

于 2009-08-10T04:49:55.590 に答える