1

C/C++ 構造体ポインターは常に最初のメンバーを指すと想定できますか?
例 1:

typedef struct {
 unsigned char  array_a[2];
 unsigned char  array_b[5];
}test;
//..
test var;
//..

上記の例では、&var は常に array_a? を指します。また、上記の例で、ポインターを unsigned char ポインターにキャストして、各バイトに個別にアクセスすることは可能ですか?
例 2:

function((unsigned char *)&var,sizeof(test));
//...
//...
void function(unsigned char *array, int len){
 int i;
 for( i=0; i<len; i++){
    array[i]++;
 }
}

それは正しく機能しますか?

注:構造体では文字がバイト単位で整列されていることがわかっているため、上記の構造体のサイズは7バイトであると想定しています。

4

4 に答える 4

9

C 構造体の場合、はい、信頼できます。これは、ほとんどすべての「オブジェクト指向」スタイルの API (GObject や GTK など) が C で動作する方法です。

C++ の場合、C 構造体と同じ方法でメモリ内に配置されることが保証されている "plain old data" (POD) 型にのみ依存できます。POD 型を正確に構成するものは少し複雑で、C++03 と C++11 の間で変更されていますが、重要なのは、型に仮想関数がある場合、それは POD ではないということです。

(C++11 ではstd::is_pod、構造体が POD 型であるかどうかをコンパイル時にテストするために使用できます。)

編集: これは、C++ で POD 型を構成するものを示しています: http://en.cppreference.com/w/cpp/concept/PODType

EDIT2:実際には、C++ 11では、PODである必要はなく、「標準レイアウト」だけで、少し弱い条件です。標準のセクション 9.2 [class.mem] パラグラフ 20 を引用します。

reinterpret_cast を使用して適切に変換された標準レイアウトの構造体オブジェクトへのポインターは、その最初のメンバー (または、そのメンバーがビットフィールドの場合は、それが存在するユニット) を指し、その逆も同様です。[ 注: したがって、標準レイアウトの構造体オブジェクト内に名前のないパディングがある場合がありますが、適切な配置を実現するために必要な場合は、先頭にはありません。— エンドノート]

于 2013-11-05T10:06:24.923 に答える
0

C の場合、これは主に実装固有ですが、実際には (#pragma pack などがない場合の) ルールは次のとおりです。

  • 構造体メンバーは、宣言された順序で格納されます。(前述のように、これは C99 標準で必要です。)
  • 必要に応じて、各構造体メンバーの前にパディングが追加され、正しい配置が保証されます。

したがって、次のような構造体が与えられます

struct test{
char ch;
int i;
}

オフセット 0 に ch があり、次にアラインするパディング バイトがあり、オフセット 2 に i があり、最後にパディング バイトが追加されて、構造体のサイズが 8 バイトの倍数になります (64 ビット マシンでは、4 バイト アラインメント32 ビットマシンでは許可される場合があります)

したがって、少なくともこの場合、C の場合、構造体ポインターが最初の配列を指すと想定できると思います。

于 2013-11-05T09:59:58.887 に答える