C構造体のサイズを16バイトの倍数(16B / 32B / 48B / ..)にしたい。サイズは関係ありません。16バイトの倍数である必要があります。
どうすればコンパイラにそれを強制できますか?
Microsoft Visual C ++の場合:
#pragma pack(push, 16)
struct _some_struct
{
...
}
#pragma pack(pop)
GCCの場合:
struct _some_struct { ... } __attribute__ ((aligned (16)));
例:
#include <stdio.h>
struct test_t {
int x;
int y;
} __attribute__((aligned(16)));
int main()
{
printf("%lu\n", sizeof(struct test_t));
return 0;
}
でコンパイルすると、gcc -o main main.c
が出力されます16
。同じことが他のコンパイラにも当てはまります。
C構造体のサイズは、構造体のメンバー、それらのタイプ、およびそれらの数によって異なります。コンパイラに構造体をあるサイズの倍数にするように強制する標準的な方法は実際にはありません。一部のコンパイラは、アライメント境界を設定できるプラグマを提供しますが、それは実際には別のことです。そして、そのような設定を持っているか、そのようなプラグマを提供するものがあるかもしれません。
ただし、これを主張する場合、1つの方法は、構造体のメモリ割り当てを実行し、メモリ割り当てを次の16バイトサイズに切り上げることです。
したがって、このような構造体がある場合。
struct _simpleStruct {
int iValueA;
int iValueB;
};
次に、次のようなことを行うことができます。
{
struct _simpleStruct *pStruct = 0;
pStruct = malloc ((sizeof(*pStruct)/16 + 1)*16);
// use the pStruct for whatever
free(pStruct);
}
これが行うことは、あなたが懸念している限り、サイズを次の16バイトサイズにプッシュすることです。ただし、メモリアロケータが行うことは、実際にそのサイズのブロックを提供することである場合とそうでない場合があります。メモリのブロックは、実際には要求よりも大きい場合があります。
これで何か特別なことをする場合、たとえば、この構造体をファイルに書き込む場合、ブロックサイズを知りたい場合は、malloc()で使用されるのと同じ計算を行う必要があります。 sizeof()演算子を使用して構造体のサイズを計算するよりも。
したがって、次のことは、などのマクロを使用して独自のsizeof()演算子を作成することです。
#define SIZEOF16(x) ((sizeof(x)/16 + 1) * 16)
私の知る限り、ポインタから割り当てられたブロックのサイズを引き出すための信頼できる方法はありません。通常、ポインタには、メモリヒープ管理機能によって使用されるメモリ割り当てブロックがあります。このブロックには、割り当てられたブロックサイズなど、実際には要求されたメモリ量よりも大きい可能性のあるさまざまなメモリ管理情報が含まれます。ただし、このブロックの形式と、提供される実際のメモリアドレスを基準にして配置される場所は、Cコンパイラの実行時間によって異なります。
ISO C標準ではアライメントがそれほど深く指定されていないため、これはコンパイラと他のツールに完全に依存します(アライメントはコンパイラの要求で発生する可能性があることを指定しますが、それを適用する方法については詳しく説明しません)。
コンパイラツールチェーンの実装固有のものを調べる必要があります。#pragma pack
それはあなたがあなたの構造定義に加えることができる(またはalign
他の何か)を提供するかもしれません。
また、これを言語拡張として提供する場合もあります。たとえば、gccを使用すると、定義に属性を追加できます。その1つが配置を制御します。
struct mystruct { int val[7]; } __attribute__ ((aligned (16)));
おそらく、二重構造体を実行して、実際の構造体を、パディングを追加できる2番目の構造体でラップすることができます。
struct payload {
int a; /*Your actual fields. */
float b;
char c;
double d;
};
struct payload_padded {
struct payload p;
char padding[16 * ((sizeof (struct payload) + 15) / 16)];
};
次に、パディングされた構造体を操作できます。
struct payload_padded a;
a.p.d = 43.3;
もちろん、構造体の最初のメンバーが構造体の開始位置から0バイトで開始するという事実を利用して、へのポインターを(であるため)struct payload_padded
へのポインターであるかのように扱うことができます。struct payload
float d_plus_2(const struct payload *p)
{
return p->d + 2;
}
/* ... */
struct payload_padded b;
const double dp2 = d_plus_2((struct payload *) &b);