日々の記録。

プログラミングのメモや感じた事などを記録。

Xcode ターミナルから楽して開く

インストール

cd ~
git clone https://github.com/hmuronaka/xcode_scripts.git
cd xcode_scripts
./install.sh

.bash_profileに以下を追加

source ~/.xcode_scripts/xcode_script.bash

出来る事

xo (xcopen) ... カレントディレクトリ以下のXcodeプロジェクト名を指定してXcodeを開く。 xc (xccd) ... カレントディレクトリ以下のXcodeプロジェクトのディレクトリに移動する。

例として、次のフォルダ構成にXcodeプロジェクトがあるとします。

~/src/xcode
       |- plugin
       |    |- XVim
       |    |    |- XVim.xcodeproj
       |    |- MCLog
       |         |- MCLog.xcodeproj
       |- lib
       |     |- Logger
       |     |    |- Logger.xcodeproj
       |     |- MyUI
       |          |- MyUI.xcopdeproj
       |          |- MyUI.xcworkspace
       |- App
       |     |- MyApp1
       |          |- MyApp1.xcodeproj
       |          |- MyApp1.xcworkspace
       |- temp
             |- Logger
                  |- Logger.xcodeproj           
 

xo (xcopen)

cd ~/src/
xo XVim # ~/src/xcode/plugin/XVim/XVim.xcodeprojを開く
xo MyUI # ~/src/xcode/lib/MyUI/MyUI.xcworkspaceを開く.xcworkspaceがある場合は、それを優先する。

xo My # ここでTabを押すと補完が表示される
MyUI MyApp1

xo # プロジェクト名無しの場合は、履歴を表示する
0: XVim: ~/src/xcode/plugin/XVim/XVim.xcodeproj
1: MyUI: ~/src/xcode/lib/MyUI/MyUI.xcworkspace
select a path >  # 0または1を入力する。qを入れるとキャンセルする。

xo Logger # 複数ある場合は、パスを選択する
0: ~/src/xcode/lib/Logger/Logger.xcodeproj
1: ~/src/tmp/Logger/Logger.xcodeproj

cd App/MyApp1
xo . # カレントディレクトリにあるXcodeプロジェクトを開く

xc (xccd)

xccdはxcopenのcd(pushd)版です。

cd ~/src/
xc XVim # ~/src/xcode/plugin/XVim/に移動する.
popd

xc MyUI # ~/src/xcode/lib/MyUI/に移動する。
popd

xc My # ここでTabを押すと補完が表示される
MyUI MyApp1

xc # プロジェクト名無しの場合は、履歴を表示する
0: XVim: ~/src/xcode/plugin/XVim/XVim.xcodeproj
1: MyUI: ~/src/xcode/lib/MyUI/MyUI.xcworkspace
select a path >  # 0または1を入力する。qを入れるとキャンセルする。

xc Logger # 複数ある場合は、パスを選択する
0: ~/src/xcode/lib/Logger/Logger.xcodeproj
1: ~/src/tmp/Logger/Logger.xcodeproj
select a path > 

コンピュータプログラミング小史とこれから

独断と偏見に基づく個人の考察でプログラミング小史と、現状のWebプログラミングについての不満と課題についてです。

長文なので先に言いたかったことを書くと

Railsって、クライアントサイドも自由に扱えない限りDRYにはなり得ないよね」

ってことです。

もし打開策が存在していれば教えて頂ければ幸いです。

小史

 昔々〜 アセンブラ(僕の知らない時代)〜

 1950年代頃の時代は、ソースコードアセンブラのような人が読めないもので、フローチャートがなければプログラムの意味が理解できないものだった。後にFortranや ALGOLといった高級言語が現れ、1970年代に入り、デニス・リッチーブライアン・カーニハンによってC言語が誕生した。これらの高級言語の登場によって、フローチャートと同じかそれ以上の内容を直接コードに書く事が可能となった。(といってもコンピュータは高価だったので、今のように気楽にコードは書くことができなかった)

〜1970年代 〜アセンブラからC言語

 高級言語が出ると同時にデータ構造とアルゴリズムについての理解が深まり、さらにダイクストラによる構造化プログラミングなどの方法論が誕生した。それと同時期に初期のオブジェクト指向が登場した(Simula67やSmalltalk、Cにクラスの概念を取り入れたC++の初期版は1979年には開発が始まっている)。

※このあたりの時代順は記憶に基づいています。

1980年〜90年代 〜メモリ管理の問題とJavaの出現〜

 80年代〜90年代になりC/C++がソフトウェア開発の主流になるにつれ、メモリ管理が大きな問題となった(これは個人の経験に基づく)。C/C++で作成されたプロセスは、プロセス内のメモリ空間に自由にアクセスできてしまうため、簡単にメモリ破壊を起こしたり、メモリリークといった問題が多発した。90年代半ばになると、オブジェクト指向言語Javaが登場し、この問題に対して2つのアプローチがとられた。1つはメモリ空間を直接扱えなくする言語的制約、もう一つは以前からLisp,Simulaによってガベージコレクションという仕組み。Java以降の言語では、ガベージコレクションの仕組みが当たり前になった(マシンスペックの向上により可能になったのかもしれない) 。特に多くのオブジェクト指向言語では、オブジェクトの生存・破壊の実装を動的メモリに依存している事が多いため(C++,Objective-C,Java,C#,Rubyなどなど)、オブジェクト指向の実践が容易となった。

Wikipedia情報によるとガベージコレクションなどはSimula67の時点で既に取り入れられていたらしい。

1990年代〜オブジェクト指向の普及〜

 90年代〜2000年にかけてオブジェクト指向の方法論が洗練されていった。デザインパターンが登場し、リファクタリングユニットテストが登場し、様々な図示化の方法(後にUMLに統一された。最近はよく分からない)が誕生した。これらの技術は主にSmalltalkNextStep(Objective-C)で登場し、C++/Javaの世界に普及していった。

2000年代前半〜オブジェクト指向に基づいたWebフレームワークの普及〜

 オブジェクト指向の技術とWebの台頭により、フレームワークという概念が一気に広まった。GUIアプリでは、既にNextStepWindowsではMFCというフレームワークが台頭していたが、Webの時代になりJavaStrutsを始め、オブジェクト指向に基づいたWeb独自のフレームワークが出現し始めた。またオープンソースなどの普及により 、高度な開発環境(javaコンパイラEclipse VSExpress、など)がより手軽に利用できるようになった。


2003年~2013年 〜暗黒期(僕にとって)〜

・・・2003年〜2013年にかけては僕にとって暗黒期で所謂IT土方をしていた。そのためプログラミング環境がどのように発展したいたのかは正直分からない。しかしWebサービスの開発は、重量級のJavaから軽量なスクリプト言語PHPへシフトし、開発プロセスも(少なくともWebでは)重たいウォーターフォールからXPを始めとするアジャイル開発などの軽量的プロセスにシフトしていった(のではないかと思う。最近のScrumの普及具合からの推測です)。又仮想化技術やAWSなどのクラウドサービスが登場し、Webサービスのあり方が大きく進歩した(のではないか・・・と思う)。

2013年。 〜気づいたらGithubやらCI(継続的インテグレーション)の時代になっていた〜

2013年、気づいたらJavaは影を潜め、Webフレームワークの主流はPHP(CakePHP)やRuby on railsといったスクリプト言語に移行していた。開発においてもGithubによるソーシャルコーディングが普及し、個人が開発したライブラリをGithubで取得して利用するのが当たり前の時代になった。またCI(継続的インテグレーション)という単体テストとデプロイを自動的に行う方法も生み出されたり、VagrantやChefといったサーバー構築や仮想環境の構築といった事も自動化され、今までは手順や手順書により属人的に行われた作業が自動化され、開発から運用に必要な時間と人が減った(減っていく)のではないかと思う。

小史は以上です。

おまけ 〜そして2014年〜

  2014年、僕は10年に及ぶIT土方をやめて、所謂ITエンジニアの世界の入り口に足を踏み入れた。会社ではsvnだったりアンチクラウドだった環境が、gitへ置き換わったりクラウドサービスを利用するようになった。スマホのアプリをObjective-Cやcocos2d-xで書き、ruby on railsでサーバサイドのプログラミングを作成するようになった。所謂ITエンジニアの入り口に立つことができた。これから5年、どのようなサービスを作るのか楽しみでもあるし怖くもある。


〜Webプログラミングに対する不満。 HTTP, JSの限界〜

いささか唐突だけど、Webプログラミングを始めて3つ不満がある。 もしかしたら既に打開策があるようなものもあるかもしれないけど、僕は知らない。

1つ目 HTTPプロトコル

Webプログラミングは、HTTPというプロトコルに縛られている。C/C++BSDソケットやWinsockを利用していた頃は、HTTPという制約がなかった。サーバーからもクライアントからも要求ができたし、文字列しか扱えないという事もなかった(昨今はWebソケットがあるから双方向の通信可能だと思うけど、未調査)。 Ruby on Railsのようにレールに従うように「HTTPに従え」と言うことなのかもしれないけど、自由度が低い気がする。

2つ目 Javasciprt

 クライアントサイドの言語がJavascriptに縛られている。これは僕には致命的に感じる。つまりサーバーサイドがJavascript(例えばNode.js)である場合を除いて、サーバーサイドとクライアントサイドで異なる言語を利用する必要がある。例えばサーバーサイドで記述された内容をクライアントで利用したい場合、それぞれの言語で2つ書くか、サーバーかクライアント(恐らくサーバー側)側に処理を統一する仕組みを設ける必要がある。何よりも今後生産性の高い言語が現れサーバーサイドにその言語を利用しても、クライアントサイドは必ずJavascriptに束縛される。これは最悪だと僕は思う。他の人はどう思うのだろうか?

3つ目 サーバーサイドとクライアントサイドで同一のオブジェクトを扱えない

 2つ目の問題の延長だけど、サーバーとクライアント間でオブジェクトがシームレスに相互作用を発揮できない。オブジェクト指向設計において、一番理想的な環境はサーバーで作成したオブジェクトがクライアント側でも操作できて、その操作の結果がサーバーに反映される事だと思う。つまり通信が完全に隠蔽されていて、サーバーとクライアントのオブジェクトが1つになっている様な状態が、理想的な状況だと思う(書いていて思い出したけど、J2EEにそんな感じのモデルがあったような・・・)。例えばGUIアプリケーションのMVCモデルというのは、modelがいてviewがいて、その両者を中継するcontrollerがいた。けどWebプログラミングでは、modelとcontroller(web側(通信も担当)), view(クライアント側),controller(view側(たまに通信も担当))といった層に分けて管理している。この2つのcontrollerはサーバサイドとクライアントサイドのオブジェクトが独立しているために発生していて、本来は不要なものだと思う。

現時点で良いと思うもの

クライアントサイドの言語の多様化

クライアントサイドがJSしかないという状況は、ある意味クライアントサイドの開発者にとっては良いかもしれないけど、今後、どんなに生産性の高い言語が出現してもJSを使い続けなければならない。それを打開するためにも、ブラウザには複数のクライアント言語を処理する仕組みがあっても良いと思う。CSSを外部のサイトから取り込めるように、rubypythonの処理系を外部から取り込む仕組みがブラウザにほしい。

サーバーサイドとクライアントサイドのオブジェクトの一元化

 例えばサーバーサイドで生成したrubyオブジェクトをクライアントサイドに渡して、クライアント側からメソッドを呼び出すとサーバー側に反映される。といったRPC的なプログラミングがより手軽に可能になればと思う。もちろん同期や並列性において別の問題を生み出す可能性があるけど。

ブラウザに代わるもの

 クライアントサイドがより柔軟になれば、HTMLにすら縛られないWebサービスという事も可能になるかもしれない。これについてはセキュリティ的な制約や、具体的にブラウザの代わりをどのように実現するかなど、今は言ったもの勝ち的なアイディアだけど、今後ブラウザという存在がネックになるのではないかな〜と思う(ブラウザとOSが歩み寄り、ブラウザがよりOSに近くなり、さらに言語の多様化が進めばブラウザの制約は薄れるかもしれない)。といってもこの場合、結局汎用性かOS依存かという問題がまた発生しそうだけど。

結論

最初にも書きましたが、この文章を書くきっかけで、自分が感じている事を端的に述べるなら

Railsって、クライアントサイドも自由に扱えない限りDRYにはなり得ないよね」

って事から始まりました。

最後まで読んで頂き、ありがとうございました。

参考文献

その3 "Hello world!!"を表示してみよう!! 中編

その2 "Hello world!"を表示してみよう 前編

前回はHello worldを表示した画面を作成しましたが、今回は作成した画面を表示してみましょう。

今回やること

  • AppDelegate.mのソースファイルの編集して画面を表示する

AppDelegateって?

画面を表示するためには、AppDelegate.mファイルを編集します。AppDelegate.mにはAppDelegateクラスについての処理が書かれています。AppDelegate.mでは、アプリが起動した場合や終了した場合の処理を記述できます。

今回は、このアプリの起動時に画面を表示する処理を追加します。

そもそもクラスって?

iOSのアプリ開発では、基本的にクラス単位に開発を行います。クラスが何かというと、一言でいうなら「特定のデータとその処理をまとめたもの」です。例えばNSStringという文字列を表現するクラスでは、文字列自身の保持とその編集方法を提供します。画面管理を行うUIViewControllerクラスでは、ユーザーが入力した情報を処理したり、画面の更新などを行います。

クラスの中身は、基本的にクラス名.h/クラス名.mという2つのファイルで定義します(3つ以上の場合もあります)。

この記事では、専門用語をざっくりと説明します。より詳しい説明は、Wikipediaのクラス)を参照してください。

AppDelegate.mの編集

ざっとAppDelegate.mの中身をみてみよう

 9 #import "AppDelegate.h"
10 
11 @implementation AppDelegate
12 
13 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 {
15     self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
16     // Override point for customization after application launch.
17    self.window.backgroundColor = [UIColor whiteColor];
18    [self.window makeKeyAndVisible];
19    return YES;
20 }

〜 中略 〜
48 
49 @end

9行目 #import "AppDelegate.h"

#import "ヘッダーファイル名" 

で、指定したファイルを読み込みます。

Objective-Cでは、クラスを作成するために、クラスの定義とクラスの実装という2つの作業を行う必要があります。 一般的に.hファイルでクラスの定義を行い、これをヘッダーファイルと呼びます。

.mファイルは、クラスの実装を行い、これをソースファイルと呼びます。 一般的にソースファイルでは、定義をするクラスのヘッダーファイルや利用するクラスのヘッダーファイルをimportで読み込む必要があります。

ここではAppDelegateを定義するために、"AppDelegate.h"を読み込んでいます。

11行目, 49行目

11 @implementation AppDelegate
 
〜中略〜

49 @end

@imlementation AppDelegateからクラスの実装が始まり、@endが実装の終了になります。クラスの実装は、この間(〜中略〜の部分)に記述します。

13〜20行目 application didFinishLaunchingWithOptionsメソッドの定義

クラスの実装といっても具体的に何をするのでしょう?答えはメソッドの定義を行います。メソッドというのは、例えばウィンドウというクラスの場合、「ウィンドウを開く」「ウィンドウを閉じる」「ウィンドウを移動する」「ウィンドウのサイズを変更する」というのがそれぞれメソッドになります。この「ウィンドウを開く」という処理を記述する作業が、メソッドの定義になります。

AppDelegateは、アプリケーションが起動したときや、停止、終了したときの処理を行うクラスなので、そうしたメソッドが定義されています。 下のソースコードは、アプリケーションが起動したときに呼ばれる「application didFinishLaunchingWithOptions」メソッドの定義です。

13 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 {
15     self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
16     // Override point for customization after application launch.
17    self.window.backgroundColor = [UIColor whiteColor];
18    [self.window makeKeyAndVisible];
19    return YES;
20 }

詳しい説明は次回以降に行い、前回作成したビューコントローラーMetronomeViewControllerをwindowに表示してみましょう。

9行目から~20行目を以下のように変更します。行頭に+が付いている行が追加した行になります。

   9 #import "AppDelegate.h"
+ 10 #import "MetronomeViewController.h"
  11
  12 @implementation AppDelegate
  13
  14 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  15 {
  16     self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
  17     // Override point for customization after application launch.
  18     self.window.backgroundColor = [UIColor whiteColor];
+ 19     MetronomeViewController* viewController = [[MetronomeViewController alloc] initWithNibName:@"MetronomeViewController" bundle:nil];
+ 20     [self.window setRootViewController:viewController];
  21     [self.window makeKeyAndVisible]; 
  22     return YES;
  23 }
  • 10行目 前回作成したMetronomeViewController.hをimportしています。クラスを利用する場合は、必ず利用するクラスのヘッダーファイルをimportします。
  • 19行目 MetronomeViewControllerのオブジェクトを生成しています。まだこの段階では、MetronomeViewControllerの画面は作られたけど、表示先が指定されていません。
  • 20行目 このアプリケーションのwindowオブジェクトに19行目で生成したMetronomeViewControllerオブジェクトを設定しています。

Command+Rで動作確認してみましょう。

Hello world!が表示されましたか?

次の画像ができたらおめでとう!!

スクリーンショット 2014-08-10 22.11.17.png

次回は、今回の内容の解説をしたいと思います。

まとめ

  • クラスは「特定のデータとその処理」をまとめたもの
  • iOSのアプリ開発は、クラス単位で作成する
  • クラスは、クラス名.h/クラス名.mという2つのファイルで定義する
  • AppDelegateクラスは、アプリケーションが起動したときや、停止、終了したときの処理を行う

その2 "Hello world!"を表示してみよう 前編

その1 夏休みにMacでメトロノームアプリを作ってみよう!!へ戻る

今回は、画面を作成して"Hello world!!"という文字列を表示してみたいと思います。

まずは実行!!

MetrnomeAppプロジェクトを作成すると、次のような画面が表示されます。

スクリーンショット 2014-08-04 22.02.42.png

まずはとにかく実行してみよう! 実行するにはキーボードのCommand+Bを押すと、ビルドという処理が行われ、実行ファイルが作成されます。そのあと、Command+Rを押すと、iOSシミュレータが起動してアプリが起動されます。

スクリーンショット 2014-08-04 22.06.35.png

はい、真っ黒です。何もしていないから空の状態のアプリが動きました。

ビルドって?

プログラムは、ソースコードを記述することによって作成します。ソースコードは、左側にあるAppDelegate.hやAppDelegate.mなどのファイルを選択すると見ることができます。またソースコードを書いたファイルをソースファイルと呼びます。

スクリーンショット 2014-08-04 22.24.10.png

この右側の文字の羅列がソースコードです。ソースコードを見たりしたり編集するためのツールをエディタと呼びます。

ソースコードは人が読める文字列ですが、コンピュータはソースコードを処理する事はできません。これをコンピュータで処理できるように変換する処理をビルドと呼びます。ビルドを行うと、ソースコードから実行ファイルを作成します。

画面を表示してみよう

大きな流れとしては、ViewControllerという画面用のソースファイルを作成し、それを表示してみましょう。

ViewControllerファイルの作成

1 Command+Nを実行して、ファイルの新規作成画面を表示し、Objective-C classを選択してNextをクリックします。

スクリーンショット 2014-08-04 22.31.31.png

2 クラス名に、MetronomeViewController、SubclassにUIViewController、Also create XIB fileにチェックを入れ、iPhoneを選択して、Nextをクリックします。(下図参照)

スクリーンショット 2014-08-04 22.35.31.png

3 ソースファイルの作成場所選択ダイアログが表示されるので、デフォルトのままCreateをクリックします。

スクリーンショット 2014-08-04 23.15.27.png

クリックすると

  • MetronomeViewController.h
  • MetronomeViewController.m
  • MetronomeViewController.xib

という3つのファイルが生成されます。

スクリーンショット 2014-08-04 23.31.36.png

MetronomeViewController.hなど、.hのファイルをヘッダーファイル、.mのファイルをソースファイル、.xibファイルを一般的にXIBファイルと呼びます。

画面の編集

1 XIBファイルを選択すると、インターフェースビルダーという画面が表示されます。この画面で、MetronomeViewControllerの画面を作成できます。

スクリーンショット 2014-08-04 23.37.29.png

中央に表示されている、白いパネルにラベルやボタンを貼り付けて、画面の見た目を作成できます。ちなみにこの白いパネルをここではビューと呼びます。

2 画面に文字列を表示するには,Labelと表示されたコントロール(ボタンやラベルなど画面に貼り付けられる部品をここではコントロールと呼びます。)をビューへドラッグアンドドロップします。

スクリーンショット 2014-08-04 23.45.09.png

右下のLabelを・・・ビューへドラッグアンドドロップ!!

スクリーンショット 2014-08-04 23.46.09.png

3 ビューに貼り付けたラベル(Labelと表示された部分)をダブルクリックすると、文字列を変更できるので、Hello world!!と入力します。

スクリーンショット 2014-08-04 23.49.42.png

若干中央からずれてしまったので、ラベルをドラッグアンドドロップして、画面中央に移動します。

スクリーンショット 2014-08-04 23.50.39.png

さて、これでCommand+B、Command+Rを押してビルドと実行をしてみましょう。。

・・・黒い画面のままですね。 なぜでしょう?

答えは、MetronomeViewControllerでHello world!!を表示する画面を作成しましたが、「この画面を表示する」という処理がありません。このようにiPhoneやコンピュータは、プログラミングで指示していない事を行いません。行う事は一つ一つ指示する必要があります。面倒ですね。 けどその指示を組み合わせる事で新しいゲームや、アプリケーション、サービスが生まれています。凄いですね!

今回はHello world!!を表示する画面の作成までです。 次回はこれを表示してみましょう!!

その3へ

その1 夏休みにMacでメトロノームアプリを作ってみよう!! 

前口上

 MacさえあればiOS(iPhone,iPad)のアプリケーションを無料で、開発し、シミュレータ上で動かす事ができます(iPhone/iPad本体に開発したアプリケーションをインストールするためには、有料の開発者用アカウントを作成する必要があります。ここではシミュレータのみを対象とします)。夏休みにiOSメトロノームアプリ開発を体験してみませんか?

対象とする方

  • 夏休みにちょっとプログラミングに触れてみたいという中学生以上の方
  • 小学生高学年以上の保護者の方。プログラミングには英語や、パソコンの知識が多少必要なので小学生が自力でやるには少々難しいです。保護者のご協力があればできるかもしれません。
  • プログラミングに興味がある大人

何が必要?

iOSの開発なので、Macである事が必須です。 後は、APPLE IDとインターネットに接続できる環境さえあれば、開発をスタートできます。!!

 僕自身プログラミングを始めたのは中学1年生の頃だから、やる気があれば中学1年でも、プログラミングはできると思います。記事の内容が、分からない場合コメント欄で質問してもらえれば、回答できる範囲で回答します。

メトロノームって?

楽器を習った(又は事がある)かたなら、ご存知かもしれませんが、 指定したテンポでリズムを刻むあれです。Youtubeにちょうど良い動画ありました。(メトロノームーテンポ63

lgi01a201402200400.jpg

これをiOSで1ステップずつ積み重ねて作成してみる、というのがこのページの目的です。

ではさっそく開発環境のXcodeをインストールしてみましょう!!

インストール手順

App Store起動します。

スクリーンショット 2014-08-04 13.45.16.png

2 検索バーでxcodeと入力し、エンターキーを押します。

スクリーンショット 2014-08-04 13.46.10.png

3 [Xcode]の無料をクリックします。

アプリケーションのインストールの手順に従い、インストールを行います。

重要: アプリケーションのインストールの際に、APPLE IDの入力が必要です。又、古いOSの場合、Xcodeをインストールできない事があります。

下記画面では、インストール済みなため、[インストール済]ノ表示になっています。 スクリーンショット 2014-08-04 13.47.54.png

4 アプリケーションフォルダから、Xcodeを実行します。

スクリーンショット 2014-08-04 14.03.21.png

以下のような画面が表示されれば、インストールは完了です。 スクリーンショット 2014-08-04 14.05.50.png

今回はここまでです。 次回は、Hello world!!を表示してみましょう。

その2 Hello world!!を表示しよう!

C++講座 その6 列挙型

列挙型を利用すると、定数の集合に名前を付ける事ができ、新しい型のように扱う事ができる。

enum Sex {
MALE,
WOMAN
};

enum ButtonType {
NORMAL,
IMAGE,
TOGGLE
};

定数は明示しなければ0から連番で0,1,2,...と付けられる。 = 1のように値を明示することもできる。

enum ResultType {
NO_ERROR = 0,
IO_ERROR = -1,
MEMORY_ERROR = -2
};

サイズ

enum内の定数値にint, unsigned intとして表現できない値が含まれていない限り、sizeof(int)よりは大きくならない。

サイズは環境による(コンパイラオプション等で変更できるかもしれない)。

小休止

cut & loopと言うiOS向けの語学用オーディオプレイヤーを作成しています。 TOEICなどの語学教材のMP3やCD音源をご利用の際にぜひ試してみてください。

‎「cut & loop 語学用オーディオプレイヤー」をApp Storeで

メリット

enumを利用する事の最大のメリットは、関数などの引数で渡す値や戻り値を明示できる点にある。

例えば

#define NO_ERROR (0)
#define IO_ERROR (-1)

int foo() {
  return NO_ERROR;
}

void bar() {
  int result = foo();
}

と書くよりも

enum Result {
IO_ERROR = -1
NO_ERROR,
};

Result foo() {
  return NO_ERROR;
}

void bar() {
  Result result = foo();
}

と書いた方が、関数の戻り値が明確になり可読性が高まる。コンパイラも型をチェックしてくれるので、誤った定数値を渡すリスクも減らせる。

デメリット

ないと思う。 以前、enum禁止のコーディングルールを見たことがあるけど信じられない。

注意点

C言語ではtypedefを付ける

C++ではtypedef不要だけど、Cでは必要(C99未確認です)。 定義ファイルをCでも共有する場合は、typedefを付ける必要がある。

通信プロトコルでの利用時

TCP/IPを利用する場合、recv/sendで構造体を直接読み書きする場合には、環境によりサイズが異なる可能性があるため、enumを利用しないこと(ちゃんと構造体毎にシリアライズする関数を定義してあるなら別かもしれませんが・・・。)。

enumの定数名はグローバルに属するため重複しやすい

namespace、classに属さないenumの定数名は、グローバルに属するため一意にする必要がある。 C++で定義する場合、classまたはnamespace内で定義すること。

enum A {
  AAA,
  BBB,
  CCC
};

enum B {
   CCC,
   DDD,
   EEE
};

void foo() {
  AAA // OK
  CCC // コンパイラはA::CかB::Cか区別できない.
}

namespace aaa {
  enum A {
    AAA,
    BBB,
    CCC
  };
}

namespace bbb {
  enum B {
     CCC,
     DDD,
     EEE
  };
}

void foo() {
  aaa::AAA // OK
  aaa::CCC // OK.
}

おまけ

定数の数を定義

enum DEVICE_TYPE {
  IPHONE_TYPE,
  IPAD_TYPE,
};

#define NUM_DEVICE_TYPE (2)

としても良いけど、定数値が0から連番で始まるなら

enum DEVICE_TYPE {
  IPHONE_TYPE,
  IPAD_TYPE,
  NUM_DEVICE_TYPE
};

これでも良い、と思う。