2

C プログラムと C++ プログラムのソース コードに違いがあることは知っていますが、これは私が求めていることではありません。

また、これはコンパイラに応じて、CPU ごと、OS ごとに異なることも知っています。

私は独学で C++ を学んでおり、両方の言語で使用できるライブラリへの参照を数多く見てきました。これは私が考え始めた - 2つの言語のバイナリ実行可能ファイルの間に大きな違いはありますか?

ライブラリを両方で簡単に使用するには、実行可能レベルで似ている必要があると思います。

実行可能ファイルを調べて、それが C または C++ ソース コードで作成されたものかどうかを判断できる状況はたくさんありますか? それとも、バイナリはかなり似ていますか?

4

5 に答える 5

7

ほとんどの場合、はい、とても簡単です。簡単に覚えられるように、私が頻繁に見たいくつかの手がかりを次に示します。

  1. C++ プログラムは、通常、マングルされた少なくともいくつかの可視シンボルで終了します。
  2. 通常、C++ プログラムには、仮想関数への呼び出しが少なくともいくつかあります。これは通常、C で通常見られるコードとはかなり異なります。
  3. this多くの C++ コンパイラは、ポインターを C++ メンバー関数に渡す際に特別な考慮事項を与える C++ の呼び出し規約を実装しています。繰り返しになりますが、thisポインターは C には存在しないため、直接の類似物はめったに見られません (ただし、場合によっては、同じ規則を使用して他のポインターを渡すため、これには注意する必要があります)。
于 2013-02-03T21:51:02.437 に答える
4

実行可能ファイルは実行可能ファイルであり、言語に関係なく実行可能ファイルです。ターゲット アーキテクチャ用にビルドされている場合は、そのアーキテクチャで実行されます。

C と C++ でコンパイルされたコードの (おそらく) 最も重要な違い、および C と C++ の両方の実行可能ファイルに対してリンクできるライブラリに関連する違いは、名前マングリングです。 基本的に: ライブラリがコンパイルされると、ライブラリに対してリンクされた実行可能ファイルが使用できる一連のシンボル (関数名、エクスポートされた変数など) がエクスポートされます。これらのシンボルの命名方法かなりコンパイラ/リンカー固有であり、後続の実行可能ファイルが互換性のない規則を使用するリンカーを使用してリンクされている場合、シンボルは正しく解決されません。さらに、C と C++ では規則が少し異なります。上にリンクされているウィキペディアの記事には、詳細が記載されています。ヘッダーファイルでエクスポートされたシンボルを宣言するとき、通常、次のような構造が表示されます。

#ifdef __cplusplus
extern "C" {
#endif

/* exported declarations here */

#ifdef __cplusplus
}
#endif

__cplusplusC++ コードのコンパイル時にのみ定義されるプリプロセッサ マクロです。ここでの考え方は、C++ でヘッダーを使用する場合、エクスポートされたシンボルの名前付けに C の方法を使用するようにコンパイラーに指示することです (" extern "C" { /* foo */ }" ブロック内で、ライブラリを C と C++ の両方で正しくリンクできます。

于 2013-02-03T21:53:17.170 に答える
2

逆アセンブルされたバイナリ コードを読み取ることで、何かが C++ であるか C であるかを判断できると思います [私がよく知っているプロセッサ アーキテクチャ、x86、x86_64、および ARM の場合]。しかし、実際には大きな違いはありません。

探すべき兆候は、「間接呼び出し」 ( function pointer calls via a table) と -thisポインターです。C はpointer to struct引数を持つことができ、関数ポインターを使用することがよくありますが、通常は C++ のように設定されていません。また、コンパイラが構造体へのポインターを取得し、小さなオフセットを追加することに気付く場合もあります。これにより、継承されたクラスの外側のレイヤーが削除されます。これはCでも発生する可能性がありますが、一般的/独特ではありません。

バイナリだけを見るのは [「頭の中で逆アセンブルを行う」ことができない限り - 特に記号が取り除かれている場合は) はるかに難しいでしょう - それは、古いビニール レコードに何がクラシック音楽の何かを見ていたかを教えてくれる男のようなものです。トラックで [ラベルを非表示] - たとえ「良い」ものであっても、ほとんどの人ができることではありません。

于 2013-02-03T22:14:37.800 に答える
1

C および C++ コンパイラによって生成されるコードは、通常は同じコードです。2 つの重要な違いがあります。

  • 名前マングリング: 各関数とグローバル変数は、コンパイル時にシンボルになります。C では、これらのシンボルの名前はソース コードでの名前と同じです。C++ では、ポリモーフィック コードを可能にするために少しマングルされています。
  • 呼び出し規則: C++ でメソッドを呼び出す場合、this-pointer は非表示の最初のパラメーターとして渡されます。C には存在しない参照渡しなど、他の規則も異なる場合があります。

次のようなブロックを使用して、C++ コンパイラに C と互換性のあるコードを生成させることができます。

extern "C" {
    /* code */
}
于 2013-02-03T21:53:48.997 に答える
1

実際には、C プログラム (または C++ プログラム) が純粋な標準 C (または C++) だけであることはめったにありません (たとえば、C99 標準にはディレクトリをスキャンする手段がありません)。そのため、プログラムは追加のライブラリを使用します。

Linux では、ほとんどのバイナリが動的にリンクされています。lddコマンドを使用して調べます。

バイナリがライブラリにリンクされている場合stdc++、ソース コードはおそらく C++ です。

ライブラリのみlibc.soがリンクされている場合、ソース コードはおそらく C のみです (ただし、ライブラリを静的にリンクすることはできlibstdc++.aます)。

objdumpまた、バイナリ ファイル (Linuxではreadelf、 、stringsなど) を操作するツールを使用してnm、それらについて詳しく調べることもできます。

于 2013-02-03T21:45:56.097 に答える