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
