簡単な C 構造体を考えてみましょう:
struct foo { const char * str; unsigned char flag; uint64_t len; };
このコードが 64 ビット マシンで実行されるプログラムの一部として実行されていると仮定します。sizeof(struct foo) の結果はどうなるでしょうか?
構造体のサイズや最適化をいじる必要がなかったほとんどの人は、それが 17 であるべきだと推測するでしょう...
...でも もう 24 時です!それはなぜですか?
この動作の理由は、コンパイラが速度向上のために構造体のレイアウトを最適化しており、整列されたメモリ アクセスがデータにアクセスする最速の方法であるという現代の標準であるためです。
これは、フィールドと CPU のタイプに応じて、データに何らかのアライメントがあり、そのアライメントが尊重されるように (または、field-address % field-alignment == 0 になるように) 配置されることを意味します。
前の例の場合、ポインタと 64 ビット フィールドは 64 ビット マシン上で 8B にアライメントされています。これは、構造体のすべてがアライメントされるレイアウトを強制するために、コンパイラがいくつかのflag フィールドと len フィールドの間のパディング:
次に、前と同じマシン上で次のような構造体が定義されている別の例を考えてみましょう。
struct bar { const char * str; short s1; int i1 short s2; int i2; };
そのサイズを計算するにはどうすればよいですか?
3 つのルールがあります:
64 ビット マシンの基本的な型の配置とサイズの簡単な要約:
type | size | alignment |
---|---|---|
char | 1 | 1 |
short | 2 | 2 |
int | 4 | 4 |
long | 8 | 8 |
float | 4 | 4 |
double | 8 | 8 |
pointers | 8 | 8 |
次の点にも注意してください:
また、非常に便利な sizeof 演算子と _Alignof 演算子を使用して、カスタム タイプの情報を取得できます。 _Alignof は C11 以降で使用可能であり、C23 以降は alignof と呼ばれることに注意してください。 C 11 以降、私が C で理解していることによれば、それは常に alignof でした。
詳細については、このトピックのバイブルは『The Lost Art of Structure Packing』です。私はこの本について、私が知っているほぼすべてのことを、多くの実践と実践経験とともに学びました。
ここでのこのトピックは、職場でかなり頻繁に取り上げられるもので、大量のデータをキューなどで継続的に送信するときに、あちこちでバイトを節約することが非常に重要です。
作業を楽にするために、ソース ファイルまたはコード スニペットを参照して、入力として渡された型に関する統計を生成するツールを作成しました。stropt (構造体オプティマイザー).
Abathargh/stropt on GitHub
ローカルに go がインストールされている場合は、すぐに進んでアプリケーションを直接ビルドまたはインストールできます。
struct foo { const char * str; unsigned char flag; uint64_t len; };
OS/アーキテクチャの組み合わせのリスト用にコンパイル済みのバイナリも、github リリース ページで提供されています。
stropt バイナリ
分析するソースを文字列として渡すことで、stropt を使用できます。
struct bar { const char * str; short s1; int i1 short s2; int i2; };
または、定義が含まれるファイルを渡すこともできます:
git clone https://github.com/Abathargh/stropt go build // or, if you want to install this directly go install github.com/Abathargh/stropt
このツールは、-optimize フラグを使用して型の最適化を行うこともでき、構造体自体であるフィールドを認識します。
冗長フラグは、内部構造体 (および共用体) をフィールドの配置とサイズとともに表示するために使用されることに注意してください。
このツールは、C コードの解析に優れた modernc.org/cc C コンパイラー フロントエンドを使用し、UI に Charmbracelet のリップグロスを使用して Go で作成されました。
これは自分用に書いていますが、喜んで公開します。これをブラウザで直接簡単に使えるように Web アプリにしたいので、おそらく次の作業はこれになると思います!
以上がC 構造体のレイアウトの最適化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。