型エンコード
ランタイムシステムを支援するために、コンパイラは各メソッドの戻り型と引数型を文字列にエンコードし、その文字列とメソッドセレクタを関連付けます。また、コンパイラが使用するエンコード方式は他のコンテキストでも便利に使用することができるため、@encode() コンパイラディレクティブを通じて一般に利用できるようになっています。型指定を渡すと、@encode() はその型をエンコードした文字列を返します。型は、int のような基本型、ポインタ、タグ付き構造体や共用体、クラス名など、実のところ、C の sizeof() 演算子の引数として使用できる任意の型を指定できます。
char *buf1 = @encode(int **);
| | char *buf2 = @encode(struct key);
| | char *buf3 = @encode(Rectangle);
| |
|
次の表に、型コードをリストします。これらの多くは、アーカイブや配布のためにオブジェクトのエンコードに使用するコードと重複することに注意してください。ただし、ここにリストしたコードの中には、コーダの記述に使用できないコードや、コーダの記述に使用することも考えられる @encode() よって生成されないコードもあります(アーカイブや配布用のオブジェクトのエンコードについては、Foundation フレームワークリファレンスの NSCoder クラス仕様を参照してください)。
表 3-1 Objective-C の型エンコード
コード |
意味 |
c |
char |
i |
int |
s |
short |
l |
long |
q |
long long |
C |
unsigned char |
I |
unsigned int |
S |
unsigned short |
L |
unsigned long |
Q |
unsigned long long |
f |
float |
d |
double |
B |
C++ の bool または C99 の _Bool |
v |
void |
* |
文字列 (char *) |
@ |
オブジェクト (静的に型定義されているもの、または id として型定義されているもの) |
# |
クラスオブジェクト(Class) |
: |
メソッドセレクタ(SEL) |
| [配列型] |
配列 |
| {名前=型...} |
構造体 |
| (型...) |
共用体 |
bnum |
num ビットのビットフィールド |
^型 |
型へのポインタ |
? |
不明な型(このコードは特に関数ポインタに使用される) |
配列の型コードは大括弧で囲まれます。配列内の要素数は、開始の大括弧の直後、配列型の前に指定されます。たとえば、float のポインタ 12 個の配列は、次のようにエンコードされます。
構造体は中括弧内、共用体は小括弧内に指定されます。まず、構造体タグがリストされ、その後に等号、構造体のフィールドに関するコードが順にリストされます。たとえば、次のような構造体があるとします。
typedef struct example {
| | id anObject;
| | char *aString;
| | int anInt;
| | } Example;
| |
|
これは、次のようにエンコードされます。
@encode() に、定義済みの型名(Example)または構造体タグ(example)のどちらを渡しても、エンコードは同じ結果になります。構造体ポインタのエンコードは、構造体のフィールドに関して同じ情報量を運びます。
しかし、別のレベルの間接参照によって、内部の型指定がなくなります。
オブジェクトは、構造体のように扱われます。たとえば、NSObject クラス名を @encode() に渡すと、次のエンコードになります。
NSObject クラスでは、1 つだけ Class 型のインスタンス変数 isa を宣言します。
@encode() ディレクティブはこれらを返しませんが、ランタイムシステムは、表 3-2 にリストした追加エンコードを使用します。これらは、プロトコルでメソッドを宣言するために使用する型修飾子です。
表 3-2 Objective-C のメソッドエンコード
コード |
意味 |
r |
const
|
n |
in
|
N |
inout
|
o |
out
|
O |
bycopy
|
R |
byref
|
V |
oneway
|
Last updated: 2003-09-16