こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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

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つよろしくお願いします。

投稿日時 - 2006-04-28 20:27:31

QNo.2119765

暇なときに回答ください

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

>ところで、intとcharを含む6バイトの構造体はパディングがされて8バイトになるのに、char6つの構造体はどうして6バイトになるんでしょうか?

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

投稿日時 - 2006-04-28 23:55:38

お礼

回答ありがとうございます。

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

投稿日時 - 2006-04-29 01:34:05

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.3

> intとcharを含む6バイトの構造体はパディングがされて8バイトになるのに、
> char6つの構造体はどうして6バイトになるんでしょうか?

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

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

投稿日時 - 2006-04-28 23:52:58

お礼

回答ありがとうございます。

リンク先のページは参考になりました。

投稿日時 - 2006-04-29 01:31:27

ANo.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になります。

投稿日時 - 2006-04-28 22:12:19

お礼

回答ありがとうございます。

リトルエンディアン、ビックエンディアンという用語ははじめて知りました。
計算のしやすさに違いがあるんですね。

>パディングと勘違いしていませんか?
どうやら勘違いしていたようです。

ところで、intとcharを含む6バイトの構造体はパディングがされて8バイトになるのに、char6つの構造体はどうして6バイトになるんでしょうか?
char型の場合はそのままのほうが扱いやすいのでしょうか?

投稿日時 - 2006-04-28 22:35:13

ANo.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の倍数バイトになると聞いたのですが

どこで、そんな話を聞きました??

投稿日時 - 2006-04-28 21:16:27

お礼

回答ありがとうございます。

逆順にデータが格納されるのは知りませんでした。
よく構造体のデータ配置の図では先頭からデータを配置しているかのように図が書いてあるので、間違って覚えてました。

>どこで、そんな話を聞きました??

たとえばhttp://www.ncad.co.jp/~komata/c-kouza7.htmとかに。
コンピュータが計算しやすいように詰め物をしてバイト数をあわせるらしいのです。

投稿日時 - 2006-04-28 22:16:20