下のソースでTESTUNIONが2バイトなぜか増え
格納データもおかしいです。これはunionの仕様でしょうか?
環境はWindows 2000,Visual C++ 6.0です。
よろしくお願いします。
以下ソースです。
#include<iostream>
#include<iomanip>
using namespace std;
namespace {
union NI{
char aa[6];
struct ST{
unsigned short ST1;
int ST2;
}TESTSTRUCT;
}TESTUNION;
union NI2{
char aa[6];
struct ST{
unsigned short ST1;
unsigned short ST2;
unsigned short ST3;
}TESTSTRUCT;
}TESTUNION2;
}
int main(){
int i;
char buff[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
for (i=0;i<=6;i++){
TESTUNION.aa[i]=buff[i];
TESTUNION2.aa[i]=buff[i];
}
cout << "TESTUNIONのサイズ:" << sizeof(TESTUNION) << endl;
cout << "TESTUNION.aaのサイズ:" << sizeof(TESTUNION.aa) << endl;
cout << "TESTUNION.TESTSTRUCTのサイズ:" << sizeof(TESTUNION.TESTSTRUCT) << endl;
cout << "TESTUNION.TESTSTRUCT.ST1のサイズ:" << sizeof(TESTUNION.TESTSTRUCT.ST1) << endl;
cout << "TESTUNION.TESTSTRUCT.ST2のサイズ:" << sizeof(TESTUNION.TESTSTRUCT.ST2) << endl;
cout << uppercase << setbase(16) << "TESTUNION.TESTSTRUCT.ST1の中身:" << TESTUNION.TESTSTRUCT.ST1 << endl;
cout << uppercase << setbase(16) << "TESTUNION.TESTSTRUCT.ST2の中身:" << TESTUNION.TESTSTRUCT.ST2 << endl;
cout << "↑全体が2バイト増え、ST1の最後から2バイト分、飛ばしている。なぜ????" << endl;
cout << "次のunionはうまくいく" << endl;
cout << "-------------------------------------------" << endl;
cout << "TESTUNION2のサイズ:" << sizeof(TESTUNION2) << endl;
cout << "TESTUNION2.aaのサイズ:" << sizeof(TESTUNION2.aa) << endl;
cout << "TESTUNION2.TESTSTRUCTのサイズ:" << sizeof(TESTUNION2.TESTSTRUCT) << endl;
cout << "TESTUNION2.TESTSTRUCT.ST1のサイズ:" << sizeof(TESTUNION2.TESTSTRUCT.ST1) << endl;
cout << "TESTUNION2.TESTSTRUCT.ST2のサイズ:" << sizeof(TESTUNION2.TESTSTRUCT.ST2) << endl;
cout << "TESTUNION2.TESTSTRUCT.ST3のサイズ:" << sizeof(TESTUNION2.TESTSTRUCT.ST3) << endl;
cout << uppercase << setbase(16) << "TESTUNION2.TESTSTRUCT.ST1の中身:" << TESTUNION2.TESTSTRUCT.ST1 << endl;
cout << uppercase << setbase(16) << "TESTUNION2.TESTSTRUCT.ST2の中身:" << TESTUNION2.TESTSTRUCT.ST2 << endl;
cout << uppercase << setbase(16) << "TESTUNION2.TESTSTRUCT.ST3の中身:" << TESTUNION2.TESTSTRUCT.ST3 << endl;
return 0;
}
/*
実行結果
TESTUNIONのサイズ:8
TESTUNION.aaのサイズ:6
TESTUNION.TESTSTRUCTのサイズ:8
TESTUNION.TESTSTRUCT.ST1のサイズ:2
TESTUNION.TESTSTRUCT.ST2のサイズ:4
TESTUNION.TESTSTRUCT.ST1の中身:2211
TESTUNION.TESTSTRUCT.ST2の中身:776655
↑全体が2バイト増え、ST1の最後から2バイト分、飛ばしている。なぜ????
次のunionはうまくいく
-------------------------------------------
TESTUNION2のサイズ:6
TESTUNION2.aaのサイズ:6
TESTUNION2.TESTSTRUCTのサイズ:6
TESTUNION2.TESTSTRUCT.ST1のサイズ:2
TESTUNION2.TESTSTRUCT.ST2のサイズ:2
TESTUNION2.TESTSTRUCT.ST3のサイズ:2
TESTUNION2.TESTSTRUCT.ST1の中身:2211
TESTUNION2.TESTSTRUCT.ST2の中身:4433
TESTUNION2.TESTSTRUCT.ST3の中身:6655
*/
> struct ST{
> unsigned short ST1;
> int ST2;
> }TESTSTRUCT;
ST2を4バイト境界に揃えるために、ST1とST2の間に2バイトのパディングが入っているのでしょう。
こんな感じ。
0 1 2 3 4 5 6 7 (パイト)
[ ST1 ][ PAD ][ ST2 ]
cout << offsetof(NI::ST, ST2) << '\n';
としてみて4が出力されればパディング入り決定。(#include <cstddef> をお忘れなく)
でもって、TESTUNION.aaのデータが一部パディング領域と重なるから2バイト分飛ばされているように見えるわけです。
ところで、
> for (i=0;i<=6;i++){
〜.aaのサイズを1バイトオーバーしていますよ。
調べてみたのですが、__attribute__ ((packed))でパディングを
抑制できるようですね。
>〜.aaのサイズを1バイトオーバーしていますよ。
すみません、ご指摘ありがとうございました。
えーと、それはgcc用の設定だと思うのですが。
VC6は#pragma packですね。(使い方は適当に検索して下さい)
ツイート | ![]() |