ページ 11

構造体とメモリについて質問です

Posted: 2019年5月31日(金) 18:12
by YUKI007BKB
構造体とメモリについて質問です.

プログラム

#include <stdio.h>
int main(void)
{
struct A{
int a;
double b;
char c,d;
}test;

printf("&test.a = %p \n", &test.a);
printf("&test.b = %p \n", &test.b);
printf("&test.c = %p \n", &test.c);
printf("&test.d = %p \n", &test.d);

return 0;
}


実行結果

&test.a = 0x7ffe805ec0c0
&test.b = 0x7ffe805ec0c8
&test.c = 0x7ffe805ec0d0
&test.d = 0x7ffe805ec0d1


質問は,a はint型で4biteのはずですが,なぜ a→b のときに 8bite進んでいるのでしょうか?

ちなみに以下のメモリ増加は正常に行われています.
b→c : +8bite
c→d : +1bite

Re: 構造体とメモリについて質問です

Posted: 2019年5月31日(金) 19:11
by shio
確か構造体は動作を高速化させるために余裕を持たせていると聞いたことがあるような気がします。

Re: 構造体とメモリについて質問です

Posted: 2019年5月31日(金) 19:25
by Math
これは構造体のメモリ上のアライメントという非常に処理系依存のお話です。

https://www.mm2d.net/main/legacy/c/c-15.html

https://wpedia.goo.ne.jp/wiki/%E3%83%87 ... 3%E3%83%88

https://qiita.com/hoboaki/items/46700f03b522193e9747

つまり この int は8 バイトアライメント(= 64ビットアライメント)です。

Re: 構造体とメモリについて質問です

Posted: 2019年5月31日(金) 20:10
by shio
質問者じゃないけど勉強になりました。ありがとう。

Re: 構造体とメモリについて質問です

Posted: 2019年5月31日(金) 20:31
by Math
#2 でshio さんのいわれる通りですね。

Re: 構造体とメモリについて質問です

Posted: 2019年5月31日(金) 21:24
by みけCAT
Math さんが書きました:
6ヶ月前
つまり この int は8 バイトアライメント(= 64ビットアライメント)です。
intではなくdoubleですね。

Re: 構造体とメモリについて質問です

Posted: 2019年6月01日(土) 07:48
by Math
>intではなくdoubleですね。
違うよ

#1
>質問は,a はint型で4biteのはずですが,なぜ a→b のときに 8bite進んでいるのでしょうか?

このint ですよ。

Re: 構造体とメモリについて質問です

Posted: 2019年6月01日(土) 16:05
by かずま
YUKI007BKB さんが書きました:
6ヶ月前
質問は,a はint型で4biteのはずですが,なぜ a→b のときに 8bite進んでいるのでしょうか?
バイトは、bite ではなく、byte です。

int型のオブジェクト(変数)のサイズは 4バイトで、メモリ上では
4バイト境界(4の倍数)にしか配置できません。すなわち、
0x7ffe805ec0c0~0x7ffe805ec0c3 のアドレスに配置できますが、
0x7ffe805ec0c1~0x7ffe805ec0c4 のアドレスに配置できまません。

double型のオブジェクト(変数)のサイズは 8バイトで、メモリ上では
8バイト境界にしか配置できません。
test.a の次のアドレスは 0x7ffe805ec0c4 ですが、これは 8バイト
境界ではありません。したがって、次の 8バイト境界である
0x7ffe805ec0c8 から test.b が始まるのです。

0x7ffe805ec0c4~0x7ffe805ec0c7 の 4バイトは、パディング(詰め物)
と呼ばれるもので、これは test.b が double型で 8バイト境界である
ことによりできたものです。
test.a の int型が 8バイト境界になったのではありません。

C の規格書では、alignment という用語を「境界調整」と翻訳しています。

また、「int型のオブジェクト(変数)のサイズは 4バイトで、メモリ上では
4バイト境界(4の倍数)にしか配置できません。」と書きましたが、
CPU によっては、どこからでも配置できるものがあります。
PC でよく使われているインテルの CPU がそうです。ただし、そういうこと
をするとメモリアクセスに時間がかかることになります。
スマートフォンなどに使われている ARM の CPU では不正な境界への
アクセスはできないようです。

Re: 構造体とメモリについて質問です

Posted: 2019年6月01日(土) 16:37
by かずま
図を書いてみると分かりやすいでしょう。

メモリ配置は次の通りです。

コード:

struct S
	+---+---+---+---+---+---+---+---+
	|  .a (int)     |   (padding)   |
	+---+---+---+---+---+---+---+---+
	|  .b (double)                  |
	+---+---+---+---+---+---+---+---+
	|.c |.d |      (padding)        |
	+---+---+---+---+---+---+---+---+
sizeof(struct A) は 24 です。

次のようなメモリ配置にしたら .b のメモリアクセスが
2回必要になって遅くなります。

コード:

struct S
	+---+---+---+---+---+---+---+---+
	|  .a (int)     | .b (double前半)|
	+---+---+---+---+---+---+---+---+
	| .b (double後半)|.c |.d |
	+---+---+---+---+---+---+
わかりましたか?
返信お待ちしております。

Re: 構造体とメモリについて質問です

Posted: 2019年6月01日(土) 20:34
by Math
dxlib ではポインターのアドレス値が4バイトか8バイトかで32ビットコンピューターか64ビットコンピューターか切り分けています。

64ビットコンピューターの場合はプログラムカウンターをインクリメントしてレジスターに64ビットデータを取り込むため8バイトのデータが必要です。
速度を優先するには半分無駄遣いをするのでしょうね。

Re: 構造体とメモリについて質問です

Posted: 2019年6月01日(土) 20:41
by Math
.Net にはInt64, Int32があるからInt64を使えばいいのだけどね。

Re: 構造体とメモリについて質問です

Posted: 2019年6月01日(土) 21:46
by みけCAT
Math さんが書きました:
6ヶ月前
>intではなくdoubleですね。
違うよ

#1
>質問は,a はint型で4biteのはずですが,なぜ a→b のときに 8bite進んでいるのでしょうか?

このint ですよ。
まず、double型のメンバbが4の倍数であり8の倍数でないアドレス(メンバaの直後)に配置されず、
8の倍数であり16の倍数ではないアドレスに配置されていることから、
この環境ではdouble型が8バイトアラインメントであることが読み取れます。
構造体中のdouble型メンバであるbを8バイトアラインメントにするため、
構造体A全体が8バイトアラインメント(もしくは8の倍数アラインメント)になると考えられます。
その結果、構造体Aの先頭にある「この」int型のメンバaは、結果的に8バイトアラインメントになりますね。
この環境で一般のintが何バイトアラインメントかは、提示された情報からは読み取れなそうです。

Re: 構造体とメモリについて質問です

Posted: 2019年6月02日(日) 17:17
by YUKI007BKB
返信遅くなってしまい申し訳ありません.
初めてこちらのサイトを利用させていただきましたが,皆さんのおかげで疑問を解消することができました.
構造体がメモリアクセスを考えて余裕をもたせていること,4byte境界,8byte境界という性質があることなど大変勉強になりました.
今後もぜひ利用させていただこうと思いますので,もし見かけたらまたお力添えをよろしくお願いいたします.
ありがとうございました.
by 駆け出しプログラマー(大学4年生)