最近更新したページ
2013-10-20
2013-09-29
2013-09-23
2012-01-07
2011-11-09
2011-10-23
2011-10-09
2011-10-01
2011-09-29
2011-09-03
2011-08-07
2011-08-02
2011-07-29
2011-07-10
2011-05-05
2011-05-04
2011-04-24
2011-04-13
2011-04-05
2011-03-26
2011-02-18
2011-02-15
2010-12-26
2010-12-07
2010-12-05
2010-11-23
2010-09-28
2010-09-23
2010-08-26
2010-08-22
2010-07-16
2010-01-17
2010-01-11
2009-10-04
2009-08-21
2009-08-13
2009-06-18
2009-06-01
2009-04-29
2009-02-16
2009-02-11
2009-02-03
2008-07-22
2008-07-21
2008-07-15
2008-07-14
2008-07-13
2008-07-12
2008-07-08
2008-07-05
2008-06-28
2008-06-17
2008-06-05
2008-06-02
2008-06-01
2008-05-29
2008-05-26
2008-05-21
2008-05-19
2008-05-18
2007-10-31
2007-10-27
2007-09-28
2007-09-23
2007-09-17
2007-09-16
2007-09-14
2007-09-11
2007-06-18
2007-04-15
2006-12-21
2006-11-30
2006-11-22
2006-08-17
2006-03-29
2006-03-28
2006-03-27

C/C++ 構造体


構造体・共用体・typedef・列挙型

 構造体に近いもの、及び、関連知識として覚えておきたい物に、共用体(union) / typedef(型の別名定義) / 列挙型(enum) がある。(これらは、基本的に C言語仕様で C++ 互換と思われる。)
 この他、C++ では、構造体を強力に拡張した Class がある。

構造体

 構造体とは、簡単に言えば、レコード定義と言って良い。データを一纏りで処理できるのは非常に便利であるが・・・利用上の制限やその実現方法について覚えることも、また多い。
 以前、VB2005 の構造体で 同一構造体型変数間で、一括転記が出来なかった(…と思う…)のに大変ショックを覚えた(「使えねぇ〜!」とか思った)ような気がするが・・・。

※VBで不可なら C/C++ Win32 では、それこそ簡単に行かない!期待しないが吉。
※メンバ単位、さらにメンバ配列は strcopy とか、やっぱやるのでしょうか?

構造体の宣言

sample2:typedef利用
typedef struct _student {
   char   class_no;
   char   name[25];
   int    age;
   double height;
   double weight;
} student ;
main () {
   // typedef使用:構造体変数の宣言と初期化。
   student studentData[30] = { … };
   // struct _student を typedef -> 別名: student で短縮宣言
}

sample1
struct _student {
   char   class_no;
   char   name[25];
   int    age;
   double height;
   double weight;
};
main () {
   // 構造体変数の宣言と初期化。
   struct _student studentData[30] = {
      { 'A', "sakura kinomoto",    13, 130.25, 46.72 },
      { 'B', "daidouji tomoyo",    14, 132.42, 45.25 },
      { 'A', "lee shaoran",        14, 145.73, 48.92 },
      { 'C', "lee meirin",         13, 140.83, 46.62 },
      { 'D', "chiharu mihara",     13, 139.73, 46.92 },
      { 'D', "takashi yamazaki",   14, 149.25, 50.68 },
      { 'A', "ereiol hiiragizawa", 13, 135.86, 47.21 },
   };
   // 使い方
   for(int i=0; i<7-1; i++) {
      printf("%c %s %d %5.2f %5.2f \n", studentData[i].class_no,
                                        studentData[i].name,
                                        studentData[i].age,
                                        studentData[i].height,
                                        studentData[i].weight  );
   }
}

▲上へ

構造体配列

sample2:
struct data {
   char   c;
   char   name[24];
   int    age;
   double sum;
   double arr[5];
} dataArr[100]; // 特に現状意味は無い。
void main() {
   struct data dat[]={
      { 'k', "sakura kinomoto", 13, 0, { 70, 61, 84, 62, 53 } },
      { 'd', "daidouji tomoyo", 14, 0, { 72, 75, 82, 70, 70 } },
      { 'l', "lee shaoran",     14, 0, { 65, 96, 94, 68, 92 } },
      { 'l', "lee meirin",      13, 0, { 52, 65, 72, 52,100 } }
   };
   // 構造体配列のアドレスとサイズ
   cout << sizeof(dat)         << endl; // 320 ?
   cout << "dat:" << &dat      << endl; // dat:0012FDF8
   cout << sizeof(dat[0].c)    << endl; // 1
   cout << sizeof(dat[0].name) << endl; // 24
   cout << sizeof(dat[0].age)  << endl; // 4
   cout << sizeof(dat[0].sum)  << endl; // 8
   cout << sizeof(dat[0].arr)  << endl; // 40
   // 構造体配列から値を取得する
   int i=2;
   dat[i].sum = dat[i].arr[0] + dat[i].arr[1] + dat[i].arr[2]
              + dat[i].arr[3] + dat[i].arr[4];
   //arrSizeof(dat);
   cout << dat                 << endl; // 0012FDF8
   cout << "dat:" << &dat      << endl; // dat:0012FDF8
   cout << dat[i].c            << endl; // l
   cout << dat[i].name         << endl; // lee shaoran
   cout << dat[i].age          << endl; // 14
   cout << dat[i].sum          << endl; // 415
   cout << dat[i].arr          << endl; // 0012FEC0
   cout << dat[i].arr[0]       << endl; // 65
   cout << dat[i].arr[1]       << endl; // 96
   cout << dat[i].arr[2]       << endl; // 94
   cout << dat[i].arr[3]       << endl; // 68
   cout << dat[i].arr[4]       << endl; // 92
}

▲上へ

構造体メンバ配列の要素数取得

※注:配列処理 - 配列の要素数取得(構造体メンバ)とほぼ同じ。

参考:表記方法メモ
(*dat).name // sakura kinomoto
dat->name   // sakura kinomoto
dat[0].name // sakura kinomoto
// 何れも同じ
※構造体メンバの配列要素数を求める。:: fn(&dat); -> fn(data* dat){…}
※動的配列の要素数取得方法は現状未確認。
sample2:
struct data {
   char   c;
   char   name[24];
   int    age;
   double sum;
   double arr[5];
};
double testSizeof(data* dat) {
   cout << "--------" << endl;
   cout << sizeof((*dat))        << endl; // 80
   cout << sizeof((*dat).c)      << endl; // 1
   cout << sizeof((*dat).name)   << endl; // 24
   cout << sizeof((*dat).age)    << endl; // 4
   cout << sizeof((*dat).sum)    << endl; // 8
   cout << sizeof((*dat).arr)    << endl; // 40 <---- サイズ取れてる?!
   cout << sizeof((*dat).arr[0]) << endl; // 8 40/8=5 配列サイズ 5
   cout << "--------" << endl;
   cout << (*dat).name           << endl; // sakura kinomoto
   cout << (*dat).sum            << endl; // 330
   cout << (*dat).arr            << endl; // 0012FF48
   cout << (*dat).arr[0]         << endl; // 70
   cout << (*dat).arr[1]         << endl; // 61
   cout << (*dat).arr[2]         << endl; // 84
   cout << (*dat).arr[3]         << endl; // 62
   cout << (*dat).arr[4]         << endl; // 53
   return 0.0;
}
void main() {
   data dat={'k',"sakura kinomoto",13,0,{70,61,84,62,53}};
   cout << sizeof(dat)      << endl; // 80
   cout << sizeof(dat.c)    << endl; // 1
   cout << sizeof(dat.name) << endl; // 24
   cout << sizeof(dat.age)  << endl; // 4
   cout << sizeof(dat.sum)  << endl; // 8
   cout << sizeof(dat.arr)  << endl; // 40
   testSizeof(&dat);
}
構造体メンバの初期値指定方法が適当なので注意。

▲上へ

構造体のメモリ使用量取得

※sizeof() 演算子で使用メモリサイズを取得する。
※環境によりメモリ使用量の調整が必要な場合、pragma (VC++の場合)等で調整する。

sample1:
//#pragma pack(push,1)
struct data {
   char   c;
   int    i;
   double d;
};
//#pragma pack(pop)
void main() {
   data dat;
   cout << sizeof(dat)   << endl; // 16 == 4(1->4へ拡張)+4byte+8byte
   cout << sizeof(dat.c) << endl; // 1  スタック=4 なら 4に拡張
   cout << sizeof(dat.i) << endl; // 4
   cout << sizeof(dat.d) << endl; // 8
}
VC++ 依存。 pragma 指定で構造体サイズの調整が可能。 push,1->dat==13 2->14 4->16 … となる。 コンパイラ間での統一が無い。移植性がなくなるので注意。

▲上へ

typedef

 typedef は、長く成りがちな構造体宣言時の名称を、短く短縮する場合利用する。
typedef struct _struct_name {
   …;
} alias_name ;
main () {
   // struct _struct_name -> alias_name に短縮して宣言
   alias_name studentData = { … };
}
※構造体(struct)以外、列挙型(enum)でも別名設定可能確認済み。共用体(union)でも同様に使用可能と思われる。

▲上へ

共用体(union)

 共用体は、構造体と書式が似ているが全く別物。実際には、共用体メンバ変数で Memory Sharing する物である。(内容非保証)
union _memoryShar {
   char   s[20];          // 文字配列型
   char   c;              // 文字型
   int    i;              // 整数型
   double d;              // 倍精度実数型
   double weight;         // 倍精度実数型
};
union _memoryShar mShar;
※注意:同時に共用体へアクセスしても正しい値は得られない。主にメモリ節約などに役に立つ?
※構造体類似のため参考程度の覚書として記載。(共用体については以上で終了)

▲上へ

列挙型(enum)

 例えば、1週の曜日、色番号(連番)、クラス番号、学年などを連番で管理する場合利用できる。

sample3;列挙型の宣言と使用例
typedef enum _week {
   MON,     TUE,WED,THU,FRI,SAT,SUN,
   Mon=0,   Tue,Wed,Thu,Fri,Sat,Sun,
   MONDAY=0,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY,
   Monday=0,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday,
   // 以下 char型は、多分誤りだが一応動く
   mon='m',tue='t',wed='w',thu='t',fri='f',sat='s',sun='s'
} week ;
void main(){
   week weekday[7] = {MON,Tue,WEDNESDAY,Thursday,FRI,Sat,SUNDAY};
   int max = sizeof(weekday)/sizeof(weekday[0]);   // 7
   for(int i=0; i<max; i++) {
      printf("%d\n", weekday[i]);                  // 0~6
   }
   printf("%c\n",mon);       // m (基本:enum型=int型列挙)
   // weekday[0] = 6; ※リスト以外の代入は (VC++ では Build Err) error
}
※何とも間抜けた例だが、多重名称列挙を説明している。
※列挙型は、基本的に int型を列挙する。char も基本は数値(0~255)なので動くが原則誤りと思われる。
※値間隔は飛んでいても問題なし。swich文などで便利かも?

sample1:
enum week {
    MONDAY,       // #define MONDAY         0
    TUESDAY,      // #define TUESDAY        1
    WEDNESDAY,    // #define WEDNESDAY      2
    THURSDAY,     // #define THURSDAY       3
    FRIDAY,       // #define FRIDAY         4
    SATURDAY,     // #define SATURDAY       5
    SUNDAY        // #define SUNDAY         6
};
// #define で値を指定しても同じだが、0 から連番となるので便利。
sample2:
enum number {
    first    = 1,  // 1
    second,        // 2 1つ前の値を 1つ加算して代入
    third,         // 3 々
    fourth,        // 4
    fifth,         // 5
    six,           // 6
    seventh,       // 7
    eighth,        // 8
    ninth,         // 9
    zero     = 0   // 0
};
// 任意の数値を割当てることも可能。

▲上へ

リンク


内部リンク


外部リンク


  • 現在ありません

▲上へ
2008年05月19日(月) 12:28:41 Modified by cafeboy1




スマートフォン版で見る