2012年2月6日月曜日

Objective-Cの整数と32bit64bit


NSIneger等のスカラ型とNSNumber型の変換についてまとめようとしたんだけど
調べてるうちにObjective-Cのint型とNSInteger型、32bitと64bitの関係について
気づいたら調べていたのでまずはそこからまとめておく。

以下、特に注意書きしていない限りは、Mac-OS-X 64bit向けにビルドした結果。

まずは、NSInteger型をint型にキャストせずに代入すると以下の警告が出る。
Implicit conversion loses integer precision: 'NSInteger'(aka 'long') to 'int'

警告の理由は、NSIntegerの持ちうる値が32bitか64bitかは処理系依存だから。
int型変数に値を代入する時はプログラマが明示的にint(32bit)と宣言する必要がある。
そして、NSIntegerはlong型 "または" int型をtypedefしたもの。
(この"または"が処理系に依存する部分)

Foundation Data Types Reference

NSInteger

Used to describe an integer.

Discussion

When building 32-bit applications, NSInteger is a 32-bit integer. A 64-bit application treats NSInteger as a 64-bit integer.

Availability

Available in Mac OS X v10.5 and later.

Declared In

QTKitDefines.h

long型、int型といったプリミティブな型をNSIntegerにラップしてくれている。
NSInteger型を使用することで、32bit環境のコードを64bit環境に移植する時にコードを変更する必要がなくなる。

ちなみに、現時点のiOSデバイスのARM processorは(現時点で)32bit onlyだそうなのでNSIntegerでは64bit整数は扱えないそうです(@see iOS: 32bit or 64 bit? - DesignersTalk)。
OSX Lionだと64bit整数を扱える。

OSX 64bit用にビルドして下記のコードを動かすと、int型以外は正しく表示される。

NSLogに渡す際のformatter文字列を%ldにしないと正しく表示されないので注意。
int型は現在4バイト32ビットで、-2147483648〜2147483647 (約マイナス20億からプラス20億) の整数値を表すことができる。

2147483647を超えると、-2147483648に戻る。
よって、以下の通り2147483647を超えて1周半くらいして1410065408になる。
1410065408=10000000000-(2147483648*4)

ちなみに、上記と同じコードをiOS向けにビルドすると、結果が変わる。

32bit整数しか扱えないので、OSXでは正しく扱えていた値がオーバーフローしてしまっている。
ただ、コンパイラの優しいところは、ちゃんと明示的に大きな値を入れているときは警告を出してくれる。
warning: implicit conversion from 'long long' to 'NSInteger' (aka 'int') changes value from 10000000000 to 1410065408 [-Wconstant-conversion,3]
まあバグが発生する時は、だいたい巨大な値が外部リソースから実行時に入ってくる時なんだけど。



コンパイラ様の言う通りに「long long」型にしたら、iOSシミュレータ用でもちゃんと動いた。
NSLogのformatter文字列を%lldにしないとやっぱり正しく表示されないけど。
long修飾子をつけるとより多くのメモリ領域を確保する模様。

しかし、結局のところint型の取りうる範囲もコンパイラ依存な訳で
Apple様以外の環境なりコンパイラなりでいろいろと結果が変わるのだろうなあ。

■主な参照ページ
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_DataTypes/Reference/reference.html
http://stackoverflow.com/questions/8813799/warning-implicit-conversion-loses-integer-precision
http://www16.ocn.ne.jp/~maccocoa/objective_c/keyword/keyword1.html
http://www.designerstalk.com/forums/mobile/59128-ios-32bit-64-bit.html

0 件のコメント:

コメントを投稿