64ビットだろうとアラインメントとパディングの話は変わらない

|

64ビット化擬きの真似事の続きの続きの続きの続きです。

取り敢えず、64ビットでの構造体のアラインメントなどを確認するだけのサンプルも作ってみました。


<注意点>

・メモリ効率を上げてシステムのパフォーマンスを改善しようと「#pragma pack」などを使用すると、アラインメントがズレたメンバにアクセスする際に性能低下 *1 を引き起こしたり、最悪の場合バスエラー *2 が発生する恐れがあります。

・前回の32ビットとの違いは、st13~st15の配列の要素数のみです。

*1:インテルの場合、x86系(x64含む) *2:インテルの場合、Itanium系


【64ビット、構造体のアラインメントデータ】

アラインメント機能64ビット確認
構造体タグsizeofalignmentpadding
本来サイズ 出力結果 メンバ最大 構造体サイズ メンバ間 最終メンバの後
st01 16 16
st02 10 16 16
st03 12 16 16
st04 16 16 16
st05 12 16 16
st06 16 16 16
st07 16 16
st08 10 16 16
st09 12 16 16
st10 16 16 16
st11 12 16 16
st12 16 16 16
st13 17 24 24
st14 26 32 32
st15 40 40 40
st21 10 16 16
st22 12 16 16
st23 802 808 808
st24 804 808 808


お試し環境
  WindowsXP 32bit Edition、Windows7 64bit Edition
  Visual C++ 2008 cross x64、native x64


/*---- 64ビット ------------------- コマンドライン -----------------------*/

D:\vc2008\x86x64>cl test.c

/*----------------------------------------------------------------------------*/


/*---- 64ビットデータ -------------------- お試し結果 --------------------*/

D:\vc2008\x86x64>test
sizeof check
diz01 = 16, &diz01 = 000000014000FB80, &diz01.no = 000000014000FB80, diz01.dat = 000000014000FB88
diz02 = 16, &diz02 = 000000014000FFE0, &diz02.no = 000000014000FFE0, diz02.dat = 000000014000FFE8
diz03 = 16, &diz03 = 000000014000F800, &diz03.no = 000000014000F800, diz03.dat = 000000014000F808
diz04 = 16, &diz04 = 000000014000FC00, &diz04.no = 000000014000FC00, diz04.dat = 000000014000FC08
diz05 = 16, &diz05 = 000000014000FB70, &diz05.no = 000000014000FB70, diz05.dat = 000000014000FB78
diz06 = 16, &diz06 = 000000014000FBD0, &diz06.no = 000000014000FBD0, diz06.dat = 000000014000FBD8

padding check
diz07 = 16, &diz07 = 000000014000FBF0, diz07.dat = 000000014000FBF0, &diz07.no = 000000014000FBF8
diz08 = 16, &diz08 = 000000014000F820, diz08.dat = 000000014000F820, &diz08.no = 000000014000F828
diz09 = 16, &diz09 = 000000014000FBE0, diz09.dat = 000000014000FBE0, &diz09.no = 000000014000FBE8
diz10 = 16, &diz10 = 000000014000FC20, diz10.dat = 000000014000FC20, &diz10.no = 000000014000FC28
diz11 = 16, &diz11 = 000000014000FC70, diz11.dat = 000000014000FC70, &diz11.no = 000000014000FC78
diz12 = 16, &diz12 = 000000014000FBC0, diz12.dat = 000000014000FBC0, &diz12.no = 000000014000FBC8

Alignment check
diz13 = 24, &diz13 = 000000014000FFC0, &diz13.no = 000000014000FFC0, diz13.dat = 000000014000FFD0
diz14 = 32, &diz14 = 000000014000FBA0, &diz14.no = 000000014000FBA0, diz14.dat = 000000014000FBB8
diz15 = 40, &diz15 = 000000014000FC40, &diz15.no = 000000014000FC40, diz15.dat = 000000014000FC60

Arithmetic check
diz21 = 16, &diz21 = 000000014000F810, &diz21.no = 000000014000F810, diz21.ptr = 000000014000F818
diz22 = 16, &diz22 = 000000014000FC10, &diz22.no = 000000014000FC10, diz22.ptr = 000000014000FC18
diz23 = 808, &diz23 = 000000014000F840, &diz23.no = 000000014000F840, diz23.ptr = 000000014000F848
diz24 = 808, &diz24 = 000000014000FC80, &diz24.no = 000000014000FC80, diz24.ptr = 000000014000FC88

sizeof(WORD) + 100 * sizeof(PVOID) = 802
sizeof(DWORD) + 100 * sizeof(PVOID) = 804
FIELD_OFFSET(struct st21, ptr) + 100 * sizeof(PVOID) = 808
FIELD_OFFSET(struct st22, ptr) + 100 * sizeof(PVOID) = 808

/*----------------------------------------------------------------------------*/


/*---- test.c ------------------- 64ビット お試しソース ------------------*/

#include <stdio.h>
#include <windows.h>

// sizeof check
struct st01 {
    char no;
    void *dat[1];
} diz01;

struct st02 {
    short no;
    void *dat[1];
} diz02;

struct st03 {
    int no;
    void *dat[1];
} diz03;

struct st04 {
    long long no;
    void *dat[1];
} diz04;

struct st05 {
    float no;
    void *dat[1];
} diz05;

struct st06 {
    double no;
    void *dat[1];
} diz06;

// padding check
struct st07 {
    void *dat[1];
    char no;
} diz07;

struct st08 {
    void *dat[1];
    short no;
} diz08;

struct st09 {
    void *dat[1];
    int no;
} diz09;

struct st10 {
    void *dat[1];
    long long no;
} diz10;

struct st11 {
    void *dat[1];
    float no;
} diz11;

struct st12 {
    void *dat[1];
    double no;
} diz12;

// Alignment check
struct st13 {
    char no[9];
    void *dat[1];
} diz13;

struct st14 {
    short no[9];
    void *dat[1];
} diz14;

struct st15 {
    long long no[4];
    void *dat[1];
} diz15;

// Arithmetic check
struct st21 {
    WORD no;
    PVOID ptr[1];
} diz21;

struct st22 {
    DWORD no;
    PVOID ptr[1];
} diz22;

struct st23 {
    WORD no;
    PVOID ptr[100];
} diz23;

struct st24 {
    DWORD no;
    PVOID ptr[100];
} diz24;

int main(int argc, char *argv[])
{
    printf("sizeof check\n");
    printf("diz01 = %d, &diz01 = %p, &diz01.no = %p, diz01.dat = %p\n", sizeof(diz01), &diz01, &diz01.no, diz01.dat);
    printf("diz02 = %d, &diz02 = %p, &diz02.no = %p, diz02.dat = %p\n", sizeof(diz02), &diz02, &diz02.no, diz02.dat);
    printf("diz03 = %d, &diz03 = %p, &diz03.no = %p, diz03.dat = %p\n", sizeof(diz03), &diz03, &diz03.no, diz03.dat);
    printf("diz04 = %d, &diz04 = %p, &diz04.no = %p, diz04.dat = %p\n", sizeof(diz04), &diz04, &diz04.no, diz04.dat);
    printf("diz05 = %d, &diz05 = %p, &diz05.no = %p, diz05.dat = %p\n", sizeof(diz05), &diz05, &diz05.no, diz05.dat);
    printf("diz06 = %d, &diz06 = %p, &diz06.no = %p, diz06.dat = %p\n", sizeof(diz06), &diz06, &diz06.no, diz06.dat);

    printf("\npadding check\n");
    printf("diz07 = %d, &diz07 = %p, diz07.dat = %p, &diz07.no = %p\n", sizeof(diz07), &diz07, diz07.dat, &diz07.no);
    printf("diz08 = %d, &diz08 = %p, diz08.dat = %p, &diz08.no = %p\n", sizeof(diz08), &diz08, diz08.dat, &diz08.no);
    printf("diz09 = %d, &diz09 = %p, diz09.dat = %p, &diz09.no = %p\n", sizeof(diz09), &diz09, diz09.dat, &diz09.no);
    printf("diz10 = %d, &diz10 = %p, diz10.dat = %p, &diz10.no = %p\n", sizeof(diz10), &diz10, diz10.dat, &diz10.no);
    printf("diz11 = %d, &diz11 = %p, diz11.dat = %p, &diz11.no = %p\n", sizeof(diz11), &diz11, diz11.dat, &diz11.no);
    printf("diz12 = %d, &diz12 = %p, diz12.dat = %p, &diz12.no = %p\n", sizeof(diz12), &diz12, diz12.dat, &diz12.no);

    printf("\nAlignment check\n");
    printf("diz13 = %d, &diz13 = %p, &diz13.no = %p, diz13.dat = %p\n", sizeof(diz13), &diz13, &diz13.no, diz13.dat);
    printf("diz14 = %d, &diz14 = %p, &diz14.no = %p, diz14.dat = %p\n", sizeof(diz14), &diz14, &diz14.no, diz14.dat);
    printf("diz15 = %d, &diz15 = %p, &diz15.no = %p, diz15.dat = %p\n", sizeof(diz15), &diz15, &diz15.no, diz15.dat);

    printf("\nArithmetic check\n");
    printf("diz21 = %d, &diz21 = %p, &diz21.no = %p, diz21.ptr = %p\n", sizeof(diz21), &diz21, &diz21.no, diz21.ptr);
    printf("diz22 = %d, &diz22 = %p, &diz22.no = %p, diz22.ptr = %p\n", sizeof(diz22), &diz22, &diz22.no, diz22.ptr);
    printf("diz23 = %d, &diz23 = %p, &diz23.no = %p, diz23.ptr = %p\n", sizeof(diz23), &diz23, &diz23.no, diz23.ptr);
    printf("diz24 = %d, &diz24 = %p, &diz24.no = %p, diz24.ptr = %p\n", sizeof(diz24), &diz24, &diz24.no, diz24.ptr);

    printf("\n");
    printf("sizeof(WORD) + 100 * sizeof(PVOID) = %d\n", sizeof(WORD) + 100 * sizeof(PVOID));
    printf("sizeof(DWORD) + 100 * sizeof(PVOID) = %d\n", sizeof(DWORD) + 100 * sizeof(PVOID));

    printf("FIELD_OFFSET(struct st21, ptr) + 100 * sizeof(PVOID) = %d\n", FIELD_OFFSET(struct st21, ptr) + 100 * sizeof(PVOID));
    printf("FIELD_OFFSET(struct st22, ptr) + 100 * sizeof(PVOID) = %d\n", FIELD_OFFSET(struct st22, ptr) + 100 * sizeof(PVOID));
}

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*============================================================================*/