C言語関係掲示板

過去ログ

No.408.構造体の padding

[戻る] [ホームページ]
No.2831

構造体宣言について
投稿者---TOKI(2002/10/02 05:41:59)


fseek関数を用いてデータの書き換えを行うときに以下のような不自然な数値に悩まされたことがあります。
たとえば、
#include <stdio.h>

struct date
{
	char sei[10];
	char mei[10];
	int age;
	float kyori;
};

main()
{
	struct date joho;

	printf("%d",sizeof(joho));
}


このとき、答えは28になりました。では、構造体変数を次のように宣言すると、

#include <stdio.h>

struct date
{
	int age;
	char sei[10];
	float kyori;
	char mei[10];
};

main()
{
	struct date joho;

	printf("%d",sizeof(joho));
}


このときの答えは、28でなく32でした。変数の型を入れ替えただけなのに違いが出てきます。
28なら納得できますが32が解せないです。
+4はどこからやってきたのでしょうか?




No.2832

Re:構造体宣言について
投稿者---PSB(2002/10/02 12:06:02)


構造体のpackingというやつですね。大体こんな法則があります。
(但し明確な取り決めはありません)
・通常の変数は4バイト境界に置かれる
・配列は4バイト境界を意識しない

開始位置  変数
0     char sei[10];
10     char mei[10];
20     int age;
24     float kyori;
28

開始位置  変数
0     int age;
4     char sei[10];
14     空き
16     float kyori;
20     char mei[10];
30     空き
32

一応、次のコードで確認できます。
printf("age:%d\n",&(((struct date*)0)->age));
printf("sei:%d\n",&(((struct date*)0)->sei[0]));
printf("kyori:%d\n",&(((struct date*)0)->kyori));
printf("mei:%d\n",&(((struct date*)0)->mei[0]));


No.2835

Re:構造体宣言について
投稿者---TOKI(2002/10/03 01:32:50)


>・通常の変数は4バイト境界に置かれる
>・配列は4バイト境界を意識しない

私の持参しているC言語参考書にはそのような説明がありませんでした。
といってもほとんど入門、つまり初心者向けの本ですけど。
理由が知れて本当に助かりました。ありがとうございます


No.2841

Re:構造体宣言について
投稿者---かずま(2002/10/03 21:28:13)


> 構造体のpackingというやつですね。大体こんな法則があります。
> (但し明確な取り決めはありません)
> ・通常の変数は4バイト境界に置かれる
> ・配列は4バイト境界を意識しない

配列は関係ありません。

・4バイトの型(int, long, float, ポインタ) は 4バイト境界に置かれる。
・2バイトの型(short) は 2バイト境界に置かれる。
・1バイトの型(char) は、どこにでも置ける。
・8バイトの型(double) は 4バイト境界または 8バイト境界に置かれる。
もちろん、これらは、CPU やコンパイラに依存します。
int やポインタが 2バイトのものもあります。

メモリー上で、4つ並んだバイトは CPU から一度にアクセスできます。
CPU とメモリーが 32本のデータバスで結ばれているからです。

4バイトの int が 4バイト境界にないと、CPU はメモリーを 2度アクセス
することになって遅くなります。Pentium はそうです。
MIPS や ARM の CPU では、4バイト境界にないと、不正アクセスになります。

このため、構造体の隣り合うメンバーの間には padding が入ることがあって、
構造体のサイズは、メンバーのサイズの合計より大きくなることがあります。