2012-07-08 12 views
33

sizeofとalignofの違いは何ですか?sizeofとalignofの違いは何ですか?

#include <iostream> 

#define SIZEOF_ALIGNOF(T) std::cout<< sizeof(T) << '/' << alignof(T) << std::endl 

int main(int, char**) 
{ 
     SIZEOF_ALIGNOF(unsigned char); 
     SIZEOF_ALIGNOF(char); 
     SIZEOF_ALIGNOF(unsigned short int); 
     SIZEOF_ALIGNOF(short int); 
     SIZEOF_ALIGNOF(unsigned int); 
     SIZEOF_ALIGNOF(int); 
     SIZEOF_ALIGNOF(float); 
     SIZEOF_ALIGNOF(unsigned long int); 
     SIZEOF_ALIGNOF(long int); 
     SIZEOF_ALIGNOF(unsigned long long int); 
     SIZEOF_ALIGNOF(long long int); 
     SIZEOF_ALIGNOF(double); 
} 

意志出力

1/1 1/1 2/2 2/2 4/4 4/4 4/4 4/4 4/4 8/8 8/8 8/8

私はアライメントが何であるか分からないと思います...?

+16

これをネイティブタイプの代わりに構造体で再度試してください。 –

+1

'指定された型のインスタンスに必要な整列をバイト数(2の整数乗)で返す ' - http://en.cppreference.com/w/cpp/language/alignof。 'sizeof'はもちろんバイト単位のサイズを与えます。 – chris

+1

多分言及する価値がある - [sizeofは常にalignofの倍数です](http://stackoverflow.com/questions/4637774/is-the-size-of-a-struct-required-to-be-an-exact-multiple -of-the-alignment-of-tha) – Steve314

答えて

3

sizeof operatorはあなたのタイプの実際の型またはインスタンスのサイズをバイト単位で与えます。

alignof operatorはあなたに与えられた型の任意のインスタンスに必要なバイトのアライメントを提供します。

+6

「整列」とは何ですか? – user1494506

14

2人の演算子は基本的に異なるものです。 sizeofは、タイプのサイズ(どのくらいのメモリを要するか)を示しますが、alignofは、どのタイプのバイトを整列する必要があるかを示します。テストしたプリミティブのサイズは、サイズと同じです(考えてみると意味があります)。

struct Foo { 
    int a; 
    float b; 
    char c; 
}; 

alignof(Foo)は4

+1

なぜですか? 'alignof'は何ですか? – user1494506

+1

@tskuzzyあなたは 'alignof(Foo)'は4を返します。しかし、それはターゲットABIに依存しています。これはia32(x86)では当てはまりますが、ARM、MIPS、PowerPCなどでは当てはまりません。 – ydroneaud

+3

4 ???私は本当に分かりません – Offirmo

54

まあ、「メモリ」は、基本的にバイトの巨大な配列で返します。

は、あなたの代わりに構造体を持っている場合、何が起こるか考えてみてください。しかし、整数のような大規模なものは、それらを格納するために1バイト以上が必要です。たとえば、32ビットの値は4バイトの連続したメモリを使用します。

さて、お使いのコンピュータのメモリモジュールは、「バイト」は、通常ではありません。それらはまた、4バイトのブロックのように、「並列に」いくつかのバイトで編成される。これは、「アライメント」は言うことです

memory byte 0 1 2 3  4 5 6 7  8 9 10 11 
integer  goooood 
        baaaaaaaaad 

:CPUの場合

は、それがより効率的にはるかに簡単に= =「クロス」など、ブロック境界が整数のようなものを読んでいないときに、より良いパフォーマンスです4の位置合わせは、の倍数であるアドレスで始まる、このタイプのデータ(または、CPUに依存しなければならない)に格納されるべきであることを意味4

== alignofが間違ってはsizeof

あなたの観察;構造を試してください。構造体も整列されます(個々のメンバーが正しいアドレスに終わる必要があるため)が、サイズはもっと大きくなります。

+14

余分なポイント - ほとんどのものではx86は非整列の読み書きを行いますが(遅くは正しく)、いくつかのアーキテクチャではすべての操作を整列させる必要があり、x86でも整列する必要がある特殊なケースがあります(SIMD指示、私は思う)。 – Steve314

+0

ありがとう!今すぐ取得します – user1494506

+2

@ user1494506 - この質問やその他の回答があなたの質問に正しく答えた場合は、*正しいことを書き留めてください。 (もちろんこれは*純粋にあなたの選択です。)人々がそう言っているので(例:私が今言っているように)回答を受け入れるようにしないでください:) – ArjunShankar

5

alignof値は、基本的なタイプのはsizeofの値と同じです。

差このような構造体を使用してとして使用される定義されたデータ型です。例えば

typedef struct { int a; double b; } S; 
//cout<<alignof(s);        outputp: 8; 
//cout<<sizeof(S);        output: 12; 

したがって、sizeof値は、指定されたデータ型に必要な合計サイズです。 であり、alignof valueは構造体内の最大要素の配置要件です。

alignof:特定の境界境界にメモリを割り当てます。

6

古い質問(答えは..とマークされていませんが)でも、この例では、Christian Stieberの答えに加えて、もう少し明示的な違いがあると考えています。またMeluhaの答えははsizeof(S)出力として、エラーが含まれている16ない12

// c has to occupy 8 bytes so that d (whose size is 8) starts on a 8 bytes boundary 
//   | 8 bytes | | 8 bytes | | 8 bytes | 
struct Bad { char c;  double d;  int i;  }; 
cout << alignof(Bad) << " " << sizeof(Bad) << endl; // 8 24 

//    | 8 bytes | | 8 bytes |  
struct Good { double d;  int i; char c;   }; 
cout << alignof(Good) << " " << sizeof(Good) << endl; // 8 16 

であるそれはまた、他のメンバーがそうであるように、それは、(この場合は二重の)最大の最初とサイズで最高の発注メンバーであることを実証していますそのメンバーによって制約される。

2

答えは、が実際に何について混乱しているようです。 2種類のアラインメントがあるため、混乱が生じる可能性があります。

1メンバーアラインメント

これは、例えば、メンバーの特定の順序内構造/クラスタイプのバイト数である方法大きいアウト呪文定性的な尺度です。一般に、コンパイラは、メンバーが構造内で降順(すなわち、最大のものから最小のものまで)のバイトサイズで順序付けられている場合、構造/クラスのインスタンスをコンパクトにすることができます。以下を検討してください。

struct A 
{ 
    char c; float f; short s; 
}; 

struct B 
{ 
    float f; short s; char c; 
}; 

どちらの構造もまったく同じ情報を含んでいます。この例のために。 float型は4バイト、short型は2、文字は1バイトです。しかし、最初の構造体Aはランダムな順序でメンバーを持ちますが、2番目の構造体Bはメンバーのバイトサイズに従って順序付けします(これは特定のアーキテクチャーでは異なる場合があります。この例では4バイト配列のx86 Intel CPUアーキテクチャーを想定しています)。あなたはサイズが7バイトであることを期待する場合は、メンバーがは、1バイトのアライメントを用いた構造にを詰めていると仮定されるだろう

printf("size of A: %d", sizeof (A)); // size of A: 12; 
printf("size of B: %d", sizeof (B)); // size of B: 8; 

:今、構造物の大きさを考慮してください。一般的に、ほとんどのコンパイラでは、歴史的な理由(ほとんどのCPUがDWORD(ダブルワード)またはQWORD(クワッドワード)汎用レジスタを使用)のために、4バイトまたは8バイトのアライメントを使用するものがあります。

パッキングを達成するために作業に2つのパディング機構があります。

  1. まず、得られたバイトのサイズが小さいか、またはバイトアライメントに等しい場合、バイトアラインメントよりも小さいバイトサイズを有する各部材は次部材(単数または複数)と「マージ」されています。構造Bでは、メンバーsとcをこのようにマージすることができます。それらの合計サイズは、c == 3バイトの場合はs + 1バイトの場合2バイト、<の場合は4バイトのアラインメントです。構造体Aでは、このようなマージは起こりません。構造体のパッキングでは、各メンバは4バイトを効率的に消費します。

  2. 構造体の合計サイズは、次の構造体がアライメント境界で開始できるように、再度埋め込まれます。例Bでは、合計バイト数は7になります。次の4バイト境界はバイト8にあります。そのため、構造体には1バイトのパディングがあり、配列の割り当ては密接なシーケンスとして許可されます。

Visual C++/GCCでは、1バイト、2以上の2バイトの倍数の異なるアラインメントが可能であることに注意してください。これは、あなたのアーキテクチャーに最適なコードを生成するコンパイラーの能力との関係で理解できます。実際、次の例では、各バイトは、各読取り操作のためのシングルバイト命令を使用して単一バイトとして読み取られます。実際には、ハードウェアは、キャッシュに読み込まれた各バイトを含むメモリ行全体をフェッチし、4バイトが同じDWORDにあり、1命令でCPUレジスタにロードされても4回命令を実行します。

#pragma pack(push,1) 
struct Bad 
{ 
    char a,b,c,d; 
}; 
#pragma pack(pop) 

2.割り当てアラインメント

これは密接に第2のパディング機構に関連しているが、しかし、前のセクションでは、のmalloc/memallocの変異体で指定することができるllocationアラインメントを説明しました割り当て関数。したがって、構造体/オブジェクト型のバイト配列が示唆するものとは異なる(通常は2の倍数)整列境界にオブジェクトを割り当てることが可能です。

size_t blockAlignment = 4*1024; // 4K page block alignment 
void* block = malloc(sizeof(T) * count, blockAlignment); 

コードは、割り当てアラインメントを使用するための4096

理由の倍数で終わるアドレスに型Tのカウントインスタンスのブロックを配置します再び純粋に建築されています。たとえば、アドレスの範囲がキャッシュレイヤーにうまく収まるため、ページアライメントされたアドレスからブロックを読み書きする方が高速です。異なる「ページ」に分割された範囲は、ページの境界を越えるときにキャッシュをゴミ箱に移動します。異なるメディア(バス・アーキテクチャー)は異なるアクセス・パターンを持ち、異なるアライメントの恩恵を受ける可能性があります。一般に、4,16,32および64Kページサイズのアラインメントは珍しいことではない。

関連する問題