黒毛和牛モモバラ切り落し100g298円

iPhoneアプリを作ってます。リリースノートとか用ブログです。

64bit ARMのプリミティブタイプの長さについて

えーと、新しいアプリを作ってる途中で64bit対応(iPhone 5sだけ?5cも?)しようとしたら、想定(というほど大したものでもなく単なる思い込み)と違う部分が結構あったのでメモっときます。

先に書いときますと、細かいことはだいたいhttp://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdfの受け売りです。LLVMも同じ仕様なのかよく分かりませんがビルドしてる限りでは同じだと思いますのでこれ以上調べてません。


で、上の資料によるとFundamental Data Typesは以下のとおり。他の型の長さも書いてましたが適宜割愛。

Machine Type Byte size Alignment
Signed half-word 2 2
Unsigned word 4 4
Signed word 4 4
Unsigned double-word 8 8
Signed double-word 8 8
Unsigned quad-word 16 16
Signed quad-word 16 16
Half precision 2 2
Single precision 4 4
Double precision 8 8
Quad precision 16 16
Data pointer 8 8
Cata pointer 8 8

次にC/C++の型長と上のMachine Typeとの対応は以下のとおり。64bitならintも64bitだと思ってたんですが違った模様。

C/C++ Type Machine Type
char unsigned byte
unsigned char unsigned byte
signed char signed byte
[signed] short signed halfword
unsigned short unsigned halfword
[signed] int signed word
unsigned int unsigned word
[signed] long signed word or signed double-word
unsigned long unsigned word or unsigned double-word
[signed] long long signed double-word
unsigned long long unsigned double-word
float single precision (IEEE 754)
double double precision (IEEE 754)
long double quad precision (IEEE 754- 2008)


でここからが本題なのですがObjective-CのNSIntegerとかは以下のように定義されてます。

// NSObjCRuntime.h
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

#define NSIntegerMax    LONG_MAX
#define NSIntegerMin    LONG_MIN
#define NSUIntegerMax   ULONG_MAX

同じくCGFloatは以下のように定義。

// CGBase.h
#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
# define CGFLOAT_IS_DOUBLE 1
# define CGFLOAT_MIN DBL_MIN
# define CGFLOAT_MAX DBL_MAX
#else
# define CGFLOAT_TYPE float
# define CGFLOAT_IS_DOUBLE 0
# define CGFLOAT_MIN FLT_MIN
# define CGFLOAT_MAX FLT_MAX
#endif

typedef CGFLOAT_TYPE CGFloat;

要はNSIntegerもCGFloatもアーキテクチャによって長さが変わるみたいらしいです。


個人的に問題になったのはCoreDataのモデル上でNSIntegerに対応する項目をintにするとどうなるかよく分からんって部分でして、64bitの実機が無いのでとりあえず全部モデル上はInteger 64にしてラッパークラスのプロパティはint64_tに変えるのがが良いのか、Integer 32にしてintのままの方が良いのかよく分からん感じです。

intのままだと64bit上ではNSNotFoundと比較できないので無しかなーという感じで新しいアプリではint64_tに変えてみたのですが、何個かデグってたので一応直したんですけどすぐ審査に提出して良いものやら悩んでおります。


てかどっちみちCoreDataのバックエンドなんかほとんどSQLiteだろうしSQLiteは内部的には型なんか無いのでInteger 32とか64とかやめてくんねーかなー、という思いも若干あったりします。いやCoreDataはSQLiteじゃねーしと言われればそれまでですが。

あとiPhone 5s上では古いXcodeでビルドしたアプリは32bitモードとかで動いたりするんですかね?でないとクラッシュするアプリもあると思うんですが、とか考えてるとなんかもう古いXcodeで良くね?って感じになるんですけどまあ文句ばっかり言っててもしょうがないのでがんばりましょう。


ということでよく分からん方は元資料あたってください。ほんでわ。