なぜなsizeofのための構造体と同一の和sizeofの各するのですか?
質問
のはなぜですか sizeof
オペレーターを返すサイズの大きい構造の合計サイズの構造です。
解決
このパディング追加を満たす配列。 データ構造配置 影響せインベスターズ-サービス本部正プログラム:
- Mis-整のアクセスがハードエラーが
SIGBUS
). - Mis-整のアクセスがソフトエラーになります。
- のいずれかに訂正ハードウェアが、ささやかな性能が劣化する
- または補正によるエミュレーションソフトウェアとなり、厳しい性能が劣化する
- また、atomicityその他の並行処理-保証が壊れ、微妙な誤差.
以下に例を示します利用の典型的な設定をx86プロセッサ(すべての使用32ビット版および64ビット版モード):
struct X
{
short s; /* 2 bytes */
/* 2 padding bytes */
int i; /* 4 bytes */
char c; /* 1 byte */
/* 3 padding bytes */
};
struct Y
{
int i; /* 4 bytes */
char c; /* 1 byte */
/* 1 padding byte */
short s; /* 2 bytes */
};
struct Z
{
int i; /* 4 bytes */
short s; /* 2 bytes */
char c; /* 1 byte */
/* 1 padding byte */
};
const int sizeX = sizeof(struct X); /* = 12 */
const int sizeY = sizeof(struct Y); /* = 8 */
const int sizeZ = sizeof(struct Z); /* = 8 */
できる限り小さくす構造を並べ替えることにより会員によるアライメントの分別によるサイズでその基礎の種類)(構造体 Z
の例です。
重要な注意:両方のCおよびC++の基準状態の構造アラインメント実装で定義されています。そのため各コンパイラがあり揃えのデータに相違により異なる、互換性のないデータレイアウトを行っております。このため、処理時の図書館で使用される異なるコンパイラでコンパイルするかを理解することが重要などのようにコンパイラを揃えます。一部のコンパイラでコンパイルしてコマンドラインの設定や特殊 #pragma
諸表の構造配置を設定します。
他のヒント
梱包およびバイトアライメントとしてのFAQ こちらの:
このためにアライメントを実施します。多くのプロセッサでのアクセス2-4バイト 数量(例えばintおよび長整数)だけでなく詰め込んでし 毎る。
例えば、皆さんがこの構造:
struct { char a[3]; short int b; long int c; char d[3]; };
今ると思っている方がいるかもしれですべきこのパック 構造体のメモリへようになります:
+-------+-------+-------+-------+ | a | b | +-------+-------+-------+-------+ | b | c | +-------+-------+-------+-------+ | c | d | +-------+-------+-------+-------+
でられたのがきっかけとなっていくプロセッサの場合、コンパイラの整 このようになります:
+-------+-------+-------+ | a | +-------+-------+-------+ | b | +-------+-------+-------+-------+ | c | +-------+-------+-------+-------+ | d | +-------+-------+-------+
を満載版、通知が出てくるんですが、それを少なくとも少し難しい だからどのようにb、cの分野を包む。このように、 このプロセッサです。そのため、ほとんどのコンパイラまでパッド の構造をされた場合と同様にエキストラは見ることができない分野のようになります:
+-------+-------+-------+-------+ | a | pad1 | +-------+-------+-------+-------+ | b | pad2 | +-------+-------+-------+-------+ | c | +-------+-------+-------+-------+ | d | pad3 | +-------+-------+-------+-------+
ご希望の場合は構造についての特定のサイズGCCのための使用例 __attribute__((packed))
.
Windowsでの設定ができます配列にバイトを利用時cl.exe compierの /Zpオプション.
通常であり、CPUへのアクセスデータと複数の4(8)によっては、台ものコンパイラです。
この物の配置を基本とさせていただきます。
必要ない理由に変えることはできない。
これによりバイトアライメントおよびパディングの構造が現れなバイト数(または語)。例えば、C Linuxの場合には、以下の3つの構造:
#include "stdio.h"
struct oneInt {
int x;
};
struct twoInts {
int x;
int y;
};
struct someBits {
int x:2;
int y:6;
};
int main (int argc, char** argv) {
printf("oneInt=%zu\n",sizeof(struct oneInt));
printf("twoInts=%zu\n",sizeof(struct twoInts));
printf("someBits=%zu\n",sizeof(struct someBits));
return 0;
}
メンバーのサイズ(バイト単位)に4バイト(32ビット単位)、8バイト(2x32ビット1バイト(2+6ビットするものではありません。上記のプログラム(Linuxを使用gcc)絵画のサイズとして4、8、4つの最後の構造が違うコミュニケーション(4×8ビットのバイトマ32bitしています。
oneInt=4
twoInts=8
someBits=4
参照:
Microsoft Visual C:
http://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx
およびGCCの請求に対応Microsoftコンパイラです。:
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
前の回答、ご注意くださいそのことにとらわれるのではなく、包装、 が会員のための保証C++.コンパイラ(かい)を追加仮想テーブルポインタをベース構造の構造です。ものの存在をバーチャルテーブルが確保されていないのは、標準の(仮想機構の実装は、指定されていない)がると結論することができなどの保証は不可能である。
いかだ 会員のため は 保証C, だかカウントで作成する際にはクロスプラットフォームまたはクロスコンパイラです。
サイズの構造は以下のとおりになり、その部品がと呼ばれるものの梱包となります。特定のプロセッサが好ましいデータサイズで作品です。最近のプロセッサ'適切なサイズが32ビット(4バイト単位)。アクセスメモリデータがこのような境界がより効率的ではないものをたぐるサイズの境界線。
ります。を考えるシンプルな構造:
struct myStruct
{
int a;
char b;
int c;
} data;
場合には機械では、32bitマシンとデータが揃32ビットの境界を直ちに問題ないことを前提として構造アライメント).この例では、その構造データの開始アドレス1024(0x400-注意のこと最低2ビットはゼロでのデータが揃って32ビットの境界).へのアクセスデータです。を作で始まり、境界0x400.へのアクセスデータです。bも大丈夫ですのでアドレス0x404-他32ビットの境界線。がunaligned構造だからこそ実現できるデータです。cアドレス0x405.の4バイトのデータです。cで0x405,0x406,0x407,0x408.32ビット、機械、システム読みます。c一時メモリサイクルのものだけなので、3、4バイト(4バイトは、次の境界).なので、システムはいう第二のメモリへのアクセスを取得し4バイト
だとするのではなくデータです。cアドレス0x405、コンパイラドの構造による3バイトを入れます。cアドレス0x408、そのシステムだけで1サイクルへのデータを読み込み、切削時間のアクセスするデータ要素による50%です。パディングスワップメモリの効率化のための処理を効率化。このコンピュータで大量のメモリ(ギガバイトのコンパイラのスワップのスピードサイズ)があります。
残念ながら、この問題になりのサポートツールすると、正しく送構造のネットワークにも書のバイナリデータをバイナリファイルです。のパディングの間に挿入要素の構造やクラスを妨害、送信されるデータファイルまたはネットワーク.書くために携帯コード(行する場合は、それぞれのコンパイラでコンパイル)までのアクセスの各要素の構造別の適正を確保するための"包".
一方、異なるコンパイラでコンパイルしてい能力の異なる管理データ構造の入った袋に同封されています。例えば、Visual C/C++のコンパイラの#pragmaパックコマンドです。ることができますデータの梱包およびアライメントを実施します。
例えば:
#pragma pack 1
struct MyStruct
{
int a;
char b;
int c;
short d;
} myData;
I = sizeof(myData);
私は、今の長さ11.のないpragma、をとることができると思いますかかいものから11-14(および一部のシステム、32)によっては、デフォルト包装のコンパイラです。
できない暗黙的または明示的に設定の配置にstruct.Structで4であることに複数の4バイトの場合でも、会員ならず、複数の4バイトです。
また、図書のとりまとめの下でのx86 32ビットのintときに比べ部品64-bitいだとは異なる結果だったとのことです。
C99N1256基準案
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
6.5.3.4のsizeofオペレーター:
3適用される場合には、オペランドと構造又は組合型 その結果、合計バイト数など、オブジェクト 内部および末尾のパディングします。
6.7.2.1構造と組合指示子:
13...が名前のない パディング内の構造オブジェクトがないのです。
と:
15あなパディングの構造です。
新C99 柔軟な配列会員の特徴 (struct S {int is[];};
しない場合がありpadding:
16日の特別の場合は、最後の要素の構造を一つ以上の名前が して不完全な配列型これを柔軟に配列す。ほとんどの状況 の柔軟な配列は無視されます。特に、サイズにしたような構造をしていて、場合に 柔軟な配列の委員は省略されたことを除いています末尾のパディングによ の漏えを示唆する.
附属書J移植性の問題 を繰り返:
以下に、指定さ:...
- この値のパディングバイトを格納する時は価値観の構造物や労働組合会議(6.2.6.1)
C++11N3337基準案
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
5.3.3Sizeof:
2適用される場合に クラスは、結果がバイト数をオブジェクトのクラスを含むパディングに必要な 置物タイプで配列に格納します。
9.2クラス会員:
ポインタを標準レイアウトのstructオブジェクトを、適切に変換を用いreinterpret_cast、ポイントがその 初期会員(またはその委員は、ビットフィールド、そしてユニットに所在す)。【ご注意:があり、その名前のない内側のパディング標準のレイアウトのstructオブジェクトがないので、 としての達成に必要な適切なアライメントを実施します。 末注意】
しか知らなかっC++を理解する注意:-)
また、その他の回答は、structできるが、通常ない仮想関数の場合は、サイズの構造体も用のスペースをvtbl.
C言葉をコンパイラの一部自由度の所在についての構造要素のメモリ:
- メモリ穴が他の部品を、最後ます。ったように、特定の種類のオブジェクトの対象コンピュータによって制限される可能性があり、境界への対応
- "メモリ穴サイズの結果に含まれまsizeof演算子です。のsizeofのみを含まないサイズの柔軟な配列で利用できることにすることでC/C++
- 一部の実装では、言語をコントロールのメモリレイアウト構造物のpragma、コンパイラオプション
言語は、C言語を提供する保証プログラマの要素にレイアウトの構造:
- コンパイラでコンパイルに必要な配列の部品化メモリのアドレス
- アドレスの最初のコンポーネントが一致の開始アドレスの構造
- 名前のないビットの分野が含まれている場合があり、構造は、必要なアドレスアライメントの隣接する要素
の問題に関する要素が配置:
- 異なるコンピュータ線、エッジオブジェクトの異なる方法
- 異なる制限の幅ビット分野
- コンピュータなどのバイトワード(インテル80x86、モトローラ68000)
どのよう配置を製作所
- の占める容積の構造として計算したサイズの揃った単一要素の配列等の構造物です。の構造 終了の最初の要素の次には、以下のような構成になに違反する要件の配列
p.s詳しい情報はこちらをご覧下さ:"サミュエルP.Harbisonに、L.ィCの照会、(5.6.2-5.6.7)"
このために速やキャッシュを考慮し、オペランドが読まれるべきからアドレスに沿って自然なサイズです。このコンパイラのパッド構造をしているので,ここでは以下の会員又は以下の構造体が揃います。
struct pixel {
unsigned char red; // 0
unsigned char green; // 1
unsigned int alpha; // 4 (gotta skip to an aligned offset)
unsigned char blue; // 8 (then skip 9 10 11)
};
// next offset: 12
のx86アーキテクチャでは常にできていずれのフェッチスしています。しかし実際には、遅くときのずれと重なる二つの異なるキャッシュライン、そのevicts二つのキャッシュラインが揃うアクセスのみ立ち退かせます。
アーキテクチャもあってトラップにずれを読み込みおよび書き込み、早期のバージョンのARMアーキテクチャの進入により、今日のモバイルCpu)...でも、実際のところも悪いデータのためです。(無視するなど、低ビット.)
最後に、このキャッシュラインできる恣意的に大きく、そのコンパイラのない方やスペースvs速トレードオフ.その代わりに、配置の決定にABIおよび表示に最小限の配置を最終的に均一に埋キャッシュする。
TL;DR: アライメントが重要です。