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 }; // 任意の数値を割当てることも可能。
▲上へ
リンク
内部リンク
- C/C++ C++/CLI C# 関連
- VC++ 2005 Express のインストール
- C/C++ の簡単なプログラム例
- 変数・定数
- プログラムの分割/ダイナミックリンクライブラリ など
- その他
- C/C++ その他::書式文字/ESC code など
- VB2005リファレンス(覚え書き)
- SQL文:SQLステートメント
- VBA(VisualBasic for Applications)
外部リンク
- 現在ありません
▲上へ
2008年05月19日(月) 12:28:41 Modified by cafeboy1