web-dev-qa-db-ja.com

CとC ++の構造体の整列

私は最近のインタビューでC++構造体フィールドの配置について尋ねられ、CおよびC++は構造体パッキングで同じ戦略に従うと理論化されました。

Hovewer、それは間違った仮定でした。インタビュアーは、一般的にCとC++は構造体を異なる方法でパッキングしているので、その逆を期待するべきではないと述べました。私見それは奇妙な声明です。バイリンガルのC/C++ヘッダーファイルで使用するC++の構造体には、pack "C"修飾子はありません。

したがって、実際には、C++で構造体を作成してCライブラリに渡すことができないことを意味する場合があります。一般に、フィールドは異なる方法で配置され、異なるオフセットを持つためです。しかし、実際には、ほとんどのプログラマーは、ポインターをCに変換するときまでこの相互運用性に真剣に依存しています [〜#〜] pod [〜#〜] 構造体をC++ラッパーへの参照にこの構造体といくつかのヘルパーメソッド。この問題を明確にしていただけませんか?

64
Minor Threat

C言語とC++言語のどちらの標準も、構造体のパディングを必要とせず、コンパイラー実装の詳細のままにします。これを厳密に解釈すると、2つの構造体が同じである保証はありません。

ただし実際には、CとC++の両方に対応するツールチェーンの特定のバージョン(GCCやClangなど)は、必要に応じて、同じ方法で同じ構造体をパックできます。これがないと、世界中の多くの量産コードが機能しません。ただし、これはツールチェーンによって保証されるものであり、not言語です。

Cのオリジナルと同様の構造体を宣言し、アクセス指定子(privatepublicおよびprotected)を追加した場合、レイアウトが変わることに注意してください。 、しかし構造体はもはや同一ではないので、それは少しストレッチです。

68
Sam Cristall

これは最も明らかに間違っていました(インタビュアー側)。低レベルの [〜#〜] api [〜#〜] 構造体を扱うすべての人にとって、CおよびC++の構造体パッキングが同じであることは明らかです。たとえば、aネットワークAPI。これらはすべてC関数であり、 'C'構造体を受け入れますが、C++コードから1日に数億回、安全に呼び出されます。

あなたはこの質問があったので幸運であるはずです。それはあなたがそこで働くべきではないことを明らかにします。

29
SergeyA

C++が開発されたとき、開発者はCプログラマーがC++開発者が保証したくないいくつかのことに依存していることを理解しましたが、それらを保証しなかった場合、有効なC++コードである多くのCコードが使用されると壊れることになりますC++コードとして。望ましくない。

それが、彼らが「POD」構造を発明した理由です。C++機能を使用しない構造体は、Cプログラムの場合とまったく同じようにC++プログラムで動作します(CコンパイラとC++コンパイラは明らかに同じ実装ではありませんが、C++コンパイラはおそらくCコンパイラから実装定義をコピーするだけです)。

有効なC++構造体でもあるプレーンなC構造体(たとえば、 "class"という名前のメンバーはない)を使用し、左中括弧の直後に "public:"を追加した場合、そのレイアウト、メンバーの順序、配置などはすべて変更できます。すべての構造体メンバーはデフォルトでパブリックですが、実際には何も変更されていません。ただし、「公開」のため、もはやPODではありません。

4
gnasher729