C言語の列挙型enumの使い方と実例を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
列挙型enumとは
列挙型enumとは,ある定数のまとまりを新しい型として取り扱うことができる型のことです.
列挙型は「整数定数」のリストとして扱われます.
列挙型の各要素に明示的に値を設定しない場合,最初の要素から順番に,0,1,2,…という値を持ちます.
例えば,教科を表す定数のまとまりの型としてenum subject型を定義します.
以下の場合は,ENGLISHが0,MATHEMATICSが1,SCIENCEが2,ALLが3という値を持ちます.
1 |
enum subject {ENGLISH, MATHEMATICS, SCIENCE, ALL}; |
列挙型で明示的に値を設定する場合は,代入演算子「=」を利用します.
例えば,enum subject型で以下のように値を設定します.
1 |
enum subject {ENGLISH = 1, MATHEMATICS = 5, SCIENCE = 2, ALL = 3}; |
また,全ての値が指定されていないときには,最後に指定された値から順番に1ずつ増えていきます.
例えば,以下のように定義したとします.
このとき,ENGLISHは0で,MATHEMATICSは5,SCIENCEは6,ALLは7になります.
1 |
enum subject {ENGLISH, MATHEMATICS = 5, SCIENCE, ALL}; |
列挙型の要素の値はコード内では重要ではなく,名前毎にユニークな整数定数を設定できることが重要です.
列挙型をわざわざ使わなくてもint型の1は英語,2は数字を表す等と決めてコードを作成することは可能です.
しかし,コードを作成している人には意味がわかりづらく,デバッグしにくくなってしまいます.
そこで,列挙型を利用し,関数の引数にENGLISHを渡すことで,英語を意味していることがわかります.
また,#defineでENGLISHやMATHEMATICS等を定数マクロで定義する場合は,同じ値を設定してしまうバグが発生する可能性がありますが,そのバグを列挙型は回避することができます.
※列挙型で明示的に同じ値を設定した場合は,このバグを回避できないことに注意して下さい.列挙型は同じ値を設定できます.
列挙型の変数は,構造体の場合と同様に利用できます.
例えば,以下のようにenum subject型の列挙型の変数sbjを定義します.
変数sbjはENGLISHやMATHEMATICS等を参照できます.
1 |
enum subject sbj; |
列挙型enumの使い方
enum subject型を利用するコードは以下になります.
このコードは,入力した数字0~3に対応した教科名を表示します.
0~3以外の場合は「Error: 4 is not a subject ID.」と表示します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> enum subject {ENGLISH, MATHEMATICS, SCIENCE, ALL}; int main(void) { enum subject sbj; printf("Please input a subject ID [0-3]: "); scanf("%d", (int *) &sbj); switch (sbj) { case ENGLISH: printf("English\n"); break; case MATHEMATICS: printf("Mathematics\n"); break; case SCIENCE: printf("Science\n"); break; case ALL: printf("All subjects\n"); break; default: fprintf(stderr, "Error: %d is not a subject ID.\n", sbj); break; } return 0; } |
実行結果は以下になります.
3行目の行末で0を入力した時は4行目で「English」,6行目の行末で4を入力した時は7行目で「Error: 4 is not a subject ID.」と表示されていることがわかります.
1 2 3 4 5 6 7 |
$ gcc enum.c $ a.out Please input a subject ID [0-3]: 0 English $ a.out Please input a subject ID [0-3]: 4 Error: 4 is not a subject ID. |
列挙型enumのポインタ型の使い方
列挙型enumのポインタ型の使い方を紹介します.
他のデータ型と同様に,列挙型enumもポインタ型で関数の引数に設定できます.
列挙型enumのポインタ型を利用するコードは以下になります.
get_day_of_week関数の引数に列挙型enum day_of_weekのポインタ型を設定しています.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> enum day_of_week { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, NR_DAYS_OF_WEEK }; const char *get_day_of_week(enum day_of_week *dow) { static const char *str[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; if (*dow >= 0 && *dow < NR_DAYS_OF_WEEK) { return str[*dow]; } return "Unknown Day of Week"; } int main(void) { enum day_of_week dow; printf("Please input a day of week [0-6]: "); scanf("%d", (int *) &dow); printf("Day of Week: %s\n", get_day_of_week(&dow)); return 0; } |
実行結果は以下になります.
3行目の行末に3と入力したら,Wednesdayと表示されていることがわかります.
1 2 3 4 |
$ gcc enum2.c $ a.out Please input a day of week [0-6]: 3 Day of Week: Wednesday |
ポインタを学びたいあなたはこちらからどうぞ.
列挙型enumのLinuxカーネルにおける実例
列挙型enumのLinuxカーネルにおける実例を紹介します.
include/linux/sched/idle.hでenum cpu_idle_type型が以下のように定義されています.
ここで,CPU_IDLE,CPU_NOT_IDLE,CPU_NEWLY_IDLEがタイプを表し,CPU_MAX_IDLE_TYPESがcpu_idle_typeの個数(値は3)を表します.
1 2 3 4 5 6 |
enum cpu_idle_type { CPU_IDLE, CPU_NOT_IDLE, CPU_NEWLY_IDLE, CPU_MAX_IDLE_TYPES }; |
enum cpu_idle_type型は,kernel/sched/stats.cのshow_schedstat関数で利用されています.
32行目でenum cpu_idle_type型の変数itypeを定義しています.
36~47行目のfor文でitypeを制御変数とし,itypeがCPU_MAX_IDLE_TYPES未満であればループの中身を実行します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
static int show_schedstat(struct seq_file *seq, void *v) { int cpu; if (v == (void *)1) { seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION); seq_printf(seq, "timestamp %lu\n", jiffies); } else { struct rq *rq; #ifdef CONFIG_SMP struct sched_domain *sd; int dcount = 0; #endif cpu = (unsigned long)(v - 2); rq = cpu_rq(cpu); /* runqueue-specific stats */ seq_printf(seq, "cpu%d %u 0 %u %u %u %u %llu %llu %lu", cpu, rq->yld_count, rq->sched_count, rq->sched_goidle, rq->ttwu_count, rq->ttwu_local, rq->rq_cpu_time, rq->rq_sched_info.run_delay, rq->rq_sched_info.pcount); seq_printf(seq, "\n"); #ifdef CONFIG_SMP /* domain-specific stats */ rcu_read_lock(); for_each_domain(cpu, sd) { enum cpu_idle_type itype; seq_printf(seq, "domain%d %*pb", dcount++, cpumask_pr_args(sched_domain_span(sd))); for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES; itype++) { seq_printf(seq, " %u %u %u %u %u %u %u %u", sd->lb_count[itype], sd->lb_balanced[itype], sd->lb_failed[itype], sd->lb_imbalance[itype], sd->lb_gained[itype], sd->lb_hot_gained[itype], sd->lb_nobusyq[itype], sd->lb_nobusyg[itype]); } seq_printf(seq, " %u %u %u %u %u %u %u %u %u %u %u %u\n", sd->alb_count, sd->alb_failed, sd->alb_pushed, sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed, sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed, sd->ttwu_wake_remote, sd->ttwu_move_affine, sd->ttwu_move_balance); } rcu_read_unlock(); #endif } return 0; } |
Linuxカーネルを学びたいあなたは,こちらからどうぞ.
まとめ
C言語で列挙型enumの使い方とLinuxカーネルにおける実例を紹介しました.
列挙型enumはユニークな定数のリストを作成したい時に便利なので,是非使いましょう!
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!