• ベストアンサー

構造体のメモリの確保のされかた

2つ質問があります。 1. #include <iostream> using namespace std; union Data { unsigned long val1_val2; struct { unsigned short val1; unsigned short val2; } value; }; int main(void) { Data data; data.val1_val2 = (40 /* val1 */ << (sizeof(data.value.val1) * 8)) + 10 /* val2 */; cout << "val1 = " << data.value.val1 << endl; cout << "val2 = " << data.value.val2 << endl; return 0; } 上記ソースコードを実行すると、「val1 = 10 val2 = 40」という結果がでます。val1は上位2バイトを指しているはずだと考えて書いたのですが、何が間違っているのでしょうか? 構造体は上に書いたメンバーを下位に割り当てていくのでしょうか? 2. 32ビットコンピューターでは構造体のサイズは4の倍数バイトになると聞いたのですが、VC++で struct s1{ char c; }; のサイズをsizeof演算子で見てみると、1バイトで struct s2{ unsigned bit: 1; }; のサイズは4バイトでした。 前者は本当に1バイトで扱われているのでしょうか? 以上2つよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.4

>ところで、intとcharを含む6バイトの構造体はパディングがされて8バイトになるのに、char6つの構造体はどうして6バイトになるんでしょうか? コンパイラの設定でパディングを詰める設定にすれば struct A{ char a; int c; }; も5バイトになります。 ただパディングを詰めると一般的に処理速度が落ちます。 long(int)は4の倍数のアドレス、shortは2の倍数に置くと処理が速いのです。 また一般的に32bitCPU(Pentium4等)ではcharよりintの計算の方が速いです。 メモリー alignment(アライメント)で調べてみてください。

minimax2005
質問者

お礼

回答ありがとうございます。 charよりintのほうが速いというのは知りませんでした。 基本データ型なのにって気もちょっとしますね。

すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.3

> intとcharを含む6バイトの構造体はパディングがされて8バイトになるのに、 > char6つの構造体はどうして6バイトになるんでしょうか?  環境によって異なりますが、CPUは変数のサイズによってアクセスできる、或いはしやすいアライメントというものが存在します。  そのアライメントを整えるためにパディングを行うわけですが、考え方としてその構造体を配列としてもアライメントが保てるようにパディングされます。

参考URL:
http://plaza.harmonix.ne.jp/~fakira/cppdoc/alig.htm
minimax2005
質問者

お礼

回答ありがとうございます。 リンク先のページは参考になりました。

すると、全ての回答が全文表示されます。
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.2

>1に関しては#1さんの言われるとおり。 「リトルエンディアン: little endian」と 「ビックエンディアン: big endian」 で調べてください。 http://e-words.jp/w/E383AAE38388E383ABE382A8E383B3E38387E382A3E382A2E383B3.html http://e-words.jp/w/E38393E38383E382B0E382A8E383B3E38387E382A3E382A2E383B3.html 人間の感覚的にはビックエンディアンが扱いやすいように思えるかもしれませんが アセンブラをやってる人にはリトルエンディアンの方が扱いやすいと思います。 多倍長の足し算とか書けばわかりますが 下桁から足していかないと繰り上がるかどうかが わからないためビックエンディアンだと 先頭ではなく後ろのバイト から見ていく必要があるのです。 >2.32ビットコンピューターでは構造体のサイズは4の倍数バイトになると聞いたのですが パディングと勘違いしていませんか? #include <stdio.h> struct A{ char a; int c; }; int main(){ printf("%d\n",sizeof(A)); return 0; } 上記コード VCやBCC,gccのデフォルトでは普通8になりますが パディングを詰める設定にすれば5になります。

minimax2005
質問者

お礼

回答ありがとうございます。 リトルエンディアン、ビックエンディアンという用語ははじめて知りました。 計算のしやすさに違いがあるんですね。 >パディングと勘違いしていませんか? どうやら勘違いしていたようです。 ところで、intとcharを含む6バイトの構造体はパディングがされて8バイトになるのに、char6つの構造体はどうして6バイトになるんでしょうか? char型の場合はそのままのほうが扱いやすいのでしょうか?

すると、全ての回答が全文表示されます。
  • don_go
  • ベストアンサー率31% (336/1059)
回答No.1

1) val1_val2 の値が16進数で、0x0028000Aになるはずだから val1 に0x0028(40)、val2 に0x000A(10)が入るはずだと 言うのでしょうが、Intel86系のCPUでは、0A 00 28 00 の 順序でLongの値がメモリに格納されます。 0x0028 0x000A は、それぞれ 28 00 と 0A 00 の順序で shortの値が格納されます。 (上位バイトと下位バイトが逆に並ぶ) 2) 32ビットコンピューターでは構造体のサイズは4の倍数バイトになると聞いたのですが どこで、そんな話を聞きました??

minimax2005
質問者

お礼

回答ありがとうございます。 逆順にデータが格納されるのは知りませんでした。 よく構造体のデータ配置の図では先頭からデータを配置しているかのように図が書いてあるので、間違って覚えてました。 >どこで、そんな話を聞きました?? たとえばhttp://www.ncad.co.jp/~komata/c-kouza7.htmとかに。 コンピュータが計算しやすいように詰め物をしてバイト数をあわせるらしいのです。

すると、全ての回答が全文表示されます。

専門家に質問してみよう