• ベストアンサー

構造体のサイズが意味不明の数になります・・・

構造体のサイズのことですが、ご存知の方がいたら教えてください。 まず、↓のプログラムを実行させたのですが、 #include<iostream> using namespace std; struct test{ short a; int b; short c; }; int main(){ cout<<sizeof(test); return 0; } 結果として8が出力されることを予想していましたが、なぜか12が出力されました。 shortは4バイトだったのかな、と思ったのですが cout<<sizeof(short); でやってみたところ結果はやはり2でした。 もちろん cout<<sizeof(int); の結果は4です。 さらに分からない所は struct test{ int b; short a; short c; }; int main(){ cout<<sizeof(test); return 0; } このように構造体の中身を入れ替えたところ正しく8が出力されました。 visual c++ 2008 express editionを使っています。 OSはvistaです。

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

  • ベストアンサー
  • jjk65536
  • ベストアンサー率59% (66/111)
回答No.7

No.6です。 手元にVCなかったので確認できなかったのですが、 GCCで期待通りに動作しましたので一応追記します。 #include <stdio.h> #pragma pack(push,1) volatile struct test{ short a; int b; short c; }; int main(void) { printf("%d\n", sizeof(struct test)); } を実行したところ、 $ ./test 8 と出力が得られました。 gccで使えるとは私も知りませんでした。びっくり。 ちなみにpackしないときは $ ./test 12 でした。

その他の回答 (6)

  • jjk65536
  • ベストアンサー率59% (66/111)
回答No.6

Cの言語仕様にはありませんが、VC++使っているのなら #pragma pack でいかがでしょう?

参考URL:
http://mag.autumn.org/Content.modf?id=20050430014843
  • Lbfuvab
  • ベストアンサー率36% (7/19)
回答No.5

freadでデータを読むなら構造体ごと書き込まずにメンバー毎に書けばどうでしょう。 それならパディングに影響を受けませんが。

  • techa
  • ベストアンサー率60% (41/68)
回答No.4

構造体境界(アライメント)の問題ですね。 私も以前、DOSのソフトからWindowsソフトへの移植のときに ぶつかりました。 私の場合はBorland C++Builderだったのですが、 #pragma pack(push,1) 構造体の定義.... #pragma pack(pop) という風にしてやるだけで対応できました。 pushの引数1は1バイト境界にするという意味で、 質問者さんの場合は2を指定すればよさそうです。 (私の場合はcharが多く含まれていたので、1にしていました) おそらくVisualCでも同様に対応できるとおもいます。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

> freadで構造体分のサイズを読み込もうとしたときにエラーが発生していました。 どんなソースコードを書いて実行したときに、 どんなエラーが出たのでしょうか? このあたりを具体的に提示してくださると、 回避策が見つかるかもしれません。見つからないかもしれません。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

構造体のアライメントからこの状態が発生します。 詳細は参考URLを参照下さい。

参考URL:
http://www.g-ishihara.com/c_st_01.htm
sorokuku
質問者

お礼

早速の回答ありがとうございます。 アライメントを回避するには並び順を工夫すればよいわけですね。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

構造体のメンバーの並び順(型がからみます)によっては、 メンバーどうしの間に「パディング(詰め物)」という どのメンバーにも割り当てられていない領域が生じる場合があります。 「構造体 パディング」あたりでググってみると、 解説しているサイトが見つかるかもしれません。

sorokuku
質問者

お礼

早速の回答ありがとうございます。 実際作ったプログラムでは、freadで構造体分のサイズを読み込もうとしたときにエラーが発生していました。 しかし、余分な領域ができてしまうなら、この方法はあんまり良くないかもしれないですね。

関連するQ&A

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

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

  • 関数、構造体

    まだ、C++の質問ですが、 struct AotU { int num; }; vodi value(Aotu a) { cin>>a.num; } void king(int k) { cout<<k; } int main() { Aotu c; value(c); king(c.num); return 0; } 上のようなコードでコンパイルができますが、 実行するとエラー出るのがなぜでしょうか? このように構造体、関数を使えないでしょうか? よろしく、お願いいたします。

  • C言語の構造体のサイズについて

    いつもお世話になっていります。 早速ですが、C言語の構造体のサイズについて教えてください。 typedef struct B { short code; char name; float price; } B; typedef struct A { B bbb[10]; double sougaku; } A; A aaa; といった構造体があった場合に、 sizeof(aaa.bbb.code) + sizeof(aaa.bbb.name) + … + sizeof(aaa.sougaku) という風に一つ一つサイズを取得し、合計して構造体のサイズを取得した場合と sizeof(aaa) という風に構造体のサイズを取得した場合のサイズの値が異なるといった現象が起きます。 その原因が分からなくて困っております。 そこで考えられる要因をお教えください。 因みに実際の構造体はサイズで言えば2500バイトくらいあります。 froat/char/double/short 型を使用しております。 よろしくお願いします。

  • C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成して

    C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成しています。 一応目的の動作はするのですが、プログラミングとして正しいか教えて頂ければと 思います。 <test.c> int main() { /* ---------------------------------------- */ /* 構造体のメンバ(NULL保障無し)がNULLか */ /* 比較するサンプル */ /* ---------------------------------------- */ char buf[50]; /* サンプル構造体 */ struct ST_test { int cd; char name[10]; int no; }; struct ST_test st_test; /* 構造体定義 */ memset(&st_test,0x00,sizeof(st_test)); /* 構造体初期化 */ memset(&buf[0],0x00,sizeof(buf)); /* 構造体初期化 */ /* 構造体に値セット */ st_test.cd = 12; memcpy(&st_test.name[0],"aabbccddee",sizeof(st_test.name)); st_test.no = 999; /* NULL判定 */ if(*st_test.name == 0x00) { printf("NULLです\n"); } else { printf("NULLではないです\n"); } return (0); }

  • 構造体の返し方

    こういう構造体があるとして、 typedef struct Day{  int day1, day2, day3; } Day; このような関数で値を入れて、 int DayTest (char s) {  Day day;  day1 = 2003;  day2 = 12;  dat3 = 31;  return < ここの返し方がわからない >; } これを main() 関数で参照できるようにするには どうすればいいのでしょうか。 printf で出力させるとかで結構です。 ポインタだとは思うのですが、うまくいきません。

  • 構造体を取得するには

    publicにcは指定してあるとしまして mainの中に構造体を引っ張り込むにはどうしたらいいのでしょうか? 形式上おかしいところもあると思いますが 宜しくお願いいたします main() { X x; } X::c() { struct a { char b[10]; char c[20]; } return ? }

  • 構造体へのポインタについて

    初心者です。 C入門書の著者のサポートページには正誤表とダウンロードしかないためこちらで質問させていただきます。 下記のコードの下から二行目の構造体へのポインタ (Car *) について、中学生に説明するように基本的な考え方、目的、書式、参考URLなどを教えて下さい。 ポインタについては、該当の章を読み直し基本事項については理解しておりますが、突然あるページから(Void *)や(Char *)など括弧で閉じるものが説明なしに出てきてちょっと混乱してます。(汗 どうぞ宜しくお願い致します。 #include<stdio.h> /* 構造体型struct Carの宣言 */ typedef struct Car{ int num; double gas; }Car; int main(void) { printf("int型のサイズは%dバイトです。¥n", sizeof(int)); printf("double型サイズは%dバイトです。¥n", sizeof(double)); printf("構造体structCar型のサイズは%dバイトです。¥n", sizeof(Car)); printf("構造体struct Car型へのポインタのサイズは%dバイトです。¥n", sizeof(Car *)); return 0; }

  • ポインタと構造体

    C言語初心者です。 下のコードはリスト構造のサンプルコードを元に自分で書き直そうとしているコードです。(なので、現時点では不完全なところ(例えばfreeしてないとか)があるのと、自分で理解出来ていない箇所があります。) 実行すると、8から3までの値が一応表示されるようになったですが、その過程の仕組みが自分でもよく理解出来ていません。 (1)tra *q = NULL; 通常、構造体のポインタを使用するときはq = &___のように他の構造体のアドレスを渡して使用出来るようにすると思いますが、ここではなぜ*qに、NULLを代入する必要があるのでしょうか。 (2)そのNULL状態のポインタqを関数printingdudeに突っ込んで結果的に8、7、6、、と出力されるまでの過程がよくわかりません。簡単に解説して頂けると助かります。(ちょっと雑な質問になってしまい申し訳ありません) typedef struct transcript{ int no; struct transcript *next; } tra; void printingdude(struct transcript *m); tra* noud(int v, tra* c); int main(){ tra *q = NULL; int i; for(i = 8; i>1; i--){ printingdude(q); q = noud(i, q); } return; } void printingdude(struct transcript *m){ if(m ==NULL) return; printf("%d\n", m->no); } tra* noud(int v, tra* c){ tra *a = (tra *) malloc(sizeof(tra)); a->no = v; a->next = c; return a; }

  • データ数の多い構造体配列

    メンバが配列である構造体配列を定義したいのですが、 struct hei { double *hight=(double*)malloc(sizeof(double) * 2*max + 1); }; int main() { struct hei h[10]; : : : という風にはできないのでしょうか。 「構文エラー : ';' が '=' の前にありません」とエラーが出てしまいます。

  • 構造体の使い方

    構造体の基本的な使い方を練習しようと思ったのですが、 なかなかスムーズにいきません。 p.d=10; の部分がおかしいようなのですが、色々試してもコンパイルできませんでした。 正しい使い方を教えていただけないでしょうか ソース ↓ #include<stdio.h> struct type{ int a; float b;  double c; }var,*p; main(){ c=9.87;      p=&var; p.d=10; p->b=1.2; printf("int:%d\n",*p); printf("float:%.1f\n",&p); printf("double:%.3lf\n",c); return 0; }

専門家に質問してみよう