質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

3回答

1110閲覧

ENUMの認識について

KKKM

総合スコア16

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/06/15 14:01

enumについて
ENUM型のメリットがわかりません

C

1typedef enum en{ 2 TOKYO, 3 OSAKA, 4 KYOTO, 5 6}JAPAN; 7 8JAPAN japan; 9japan = TOKYO;

上記のようなコーディングがあったとします。

C

1#define TOKYO 0 2#define OSAKA 1 3#define KYOTO 2 4

のようにいちいち列挙する必要がない点はENUMのメリットであるということはわかります。
ただ定義したENUM型のインスタンスを作って利用することのメリットがわかりません。
わざわざenum型のインスタンスを作らなくても以下のように
int japan = TOKYO;
のような使い方でもよいと思うのですが...

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

#define による定数の定義というのはあくまでもプリプロセッサが行う「字句的な置き換え」であって、処理のレイヤが違うのです。 マクロは通常のスコープの一般原則を超越してあらゆる箇所に現れるトークンを置き換えます。

通常の変数や (enum による定義を含む) 定数は同名のものがあった場合にはよりスコープが狭いほうが優先されるという原則がありますが、マクロはそうではありません。

単純な例でいえば

c

1#include <stdio.h> 2 3enum JAPAN{ 4 TOKYO, 5 OSAKA, 6 KYOTO, 7}; 8 9int main(void) { 10 const int TOKYO = 10; 11 printf("%d\n", TOKYO); 12}

といったように enum 内で定義した TOKYO よりも main 内で定義した TOKYO のほうが優先されます。

これを enum ではなく #define による定義にするとどうなるでしょうか。

c

1#include <stdio.h> 2 3#define TOKYO 0 4#define OSAKA 1 5#define KYOTO 2 6 7int main(void) { 8 const int TOKYO = 10; 9 printf("%d\n", TOKYO); 10}

プリプロセッサによる置き換えによって

c

1#include <stdio.h> 2 3int main(void) { 4 const int 0 = 10; 5 printf("%d\n", TOKYO); 6}

と同様の状態になってエラーになってしまいます。

#define による定義では全部を大文字の名前にする (それ以外はそうしない) という習慣があるのはマクロ名がマクロでない名前と衝突するとろくでもないことが起こるのがわかっているからです。


もうひとつの理由は「意図の表現」です。 プログラムはコンパイラが解釈して実行プログラムを生成するというだけでなくあなた以外のプログラマが読むこともあるという事実も忘れてはいけません。

たとえば

c

1#include <stdio.h> 2 3enum JAPAN { 4 TOKYO, 5 OSAKA, 6 KYOTO, 7}; 8 9void foo(enum JAPAN x) { 10 printf("%d", x); 11}

と書いてあれば「foo という関数は (引数として) 日本のどこかであるかを受け取るのだな」という意図が読み取れます。

これが

c

1#include <stdio.h> 2 3#define TOKYO 0 4#define OSAKA 1 5#define KYOTO 2 6 7void foo(int x) { 8 printf("%d", x); 9}

だと foo が受けとる変数が何者であるのかというのは (実質の処理内容が同じだとしても) 字面から読み取るのが難しくなります。

投稿2021/06/15 18:48

SaitoAtsushi

総合スコア5446

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

enumを使用すると、#defineで一つづつ定義していると定義がたくさんあったときに番号が重複したりするようなミスを防ぐことができます。
また、enumの識別名で内容をカテゴライズできるのでコードの可読性がよくなる可能性があります。
同じようなことを#define定義でやろうとすると定義名が長くなりがちで、定義名が重複したときにコンパイルエラーで検出できないので不具合を見逃す可能性があります。

投稿2021/06/15 15:05

編集2021/06/15 15:15
TaroToyotomi

総合スコア1430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

わざわざenum型のインスタンスを作らなくても

わざわざint型のインスタンスにenumの値を突っ込まなくてもいいと思います。
なにかint型に比べてenumの方がコストがかかることがありますか? ソースコード上で文字数が多い、とか?

enumは「型」です。つまり、データの意味がそういうものである、ということを示します。enum xx型は列挙された要素の集合である、ということを言いたいから列挙型を定義したわけです。その型の変数を宣言して使うことになにか「わざわざ」という要素があるでしょうか? enumを定義した時点で「わざわざ」の議論は終わっているはずです。

また、JavaとかC#とか、新しい言語ではintとenumが明確に分離される傾向にあることはどのように考えますか? 実装上の都合とCの性格(型変換に鷹揚)の関係からCでは難なくint型の変数にenumの値を突っ込めますけれど、それは「できてしまう」次元でしょう。

とかなんとかいいながら、enumで状態を定義するとき等、

enum STATE{ A, B, C, MAX } int a[MAX];

なんてことは時々やってたりする。便利だから...

投稿2021/06/15 22:04

thkana

総合スコア7639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問