64ビットプログラミングのポイント64ビットコンピューティング最前線(2/3 ページ)

» 2005年06月14日 00時00分 公開
[C MAGAZINE]

long型を4バイトデータに使わない

 先の説明に関連しますが、long型を4バイトと仮定してはいけません。

 16ビット環境でプログラミング経験のあるプログラマは、int型が2バイトになるかもしれないということを知っています。このため、長さが4バイトに決められているデータ領域が必要なときに、int型を避けてうっかりlong型を使ってしまうことがあります。しかし、LP64やILP64ではlong型が8バイトなので、こうしてしまうと期待した結果が得られなくなることがあります。

 決まった長さのデータ領域が必要な場合は、プログラムのどこか1か所で独自の変数の型を定義しておき、残りの部分ではこの変数型を使うようにします。たとえば、ILP32やLP64、LLP64で4バイトの整数型を使いたいときは、

typedef int int32;

のようにあらかじめ宣言しておき、プログラムでは常にint32型を使うようにします。

 こうすることで、int型が4バイトではない環境にプログラムを持っていく場合でもtypedefの宣言を単純に書き換えるだけで済みます。

定数の補数表現に気をつける

 32ビット環境のプログラム内で比較や関数の戻り値として「-1」というマイナスの定数を使う場合があったとします。

 まれなケースかもしれませんが、これをわざわざ「0xffffffff」といった形に補数表現して記述するようなプログラムの場合、64ビット環境では「-1」ではなくなってしまうことがあります。したがって、定数の扱いにも注意しなければなりません。

 補数表現例の対応表をTable7に示しますので参考にしてください。

Table 7 補数表現例の対応表
データモデル
(例)
補数表現
(int型)
補数表現
(long型)
補数表現
(ポインタ)
ILP32 -1 0xffffffff 0xffffffff 0xffffffff
LLP64 -1 0xffffffff 0xffffffff 0xffffffffffffffff
LP64 -1 0xffffffff 0xffffffffffffffff 0xffffffffffffffff
ILP64 -1 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff

printf関数のフォーマットに注意する

 32ビット環境(ILP32)に慣れているプログラマは、しばしばList3のような間違ったコードを書くことがあります。

List3 間違ったprintf関数の使い方
long value_l;
...
printf("%d\n"), value_l);

 ILP32やLLP64では、

sizeof(long) == sizeof(int)

なので、このコードは正しく動きます。

 しかし、“%d”はint型変数を示すフォーマット指定なので、LP64ではlong型変数value_lの半分のビット幅しかprintf関数に渡されないことになります。したがって、このコードはList4のように書き直されるべきです。

List4 64ビット環境でlong型の変数を出力させる場合
long value_l;
...
printf("%ld\n", value_l);

 LLP64の場合でもポインタは64ビットになるので、ポインタの値をprintf関数に渡す場合は、

printf("%p\n", value_p);

のように記述しなければなりません。

 また、この例と同様に、ほかのprintf関数群やsscanf関数などでも正しいフォーマットで指定する必要があります。その例として、Windowsで__int64型の変数を出力させる場合をList5に示します。

List5 Windowsで__int64型の変数を出力させる場合
__int64 value_64;
...
printf("%I64d\n", value_64);

Copyright(C) 2010 SOFTBANK Creative Inc. All Right Reserved.

注目のテーマ