2013-06-18 25 views
14

プロジェクトでこのコードを見ました。同じ行に2回キャストする

bのタイプはvoid*です:

void *b = ...; 
int a = (int) (unsigned long) b; 

は無意味このラインですか?すべての場合、a = (int) bと同じですか?

答えて

22

これはおそらく、unsigned longが64ビットの量でポインタを保持するのに十分な大きさですが、intはポインタを保持するのに十分な大きさではない64ビットUnixシステムでのコンパイラ警告を回避します。 (unsigned long)へのキャストは、アドレスのすべてのビットを保持します。後でintにキャストすると、アドレスの上位32ビットがスローされますが、デフォルトでは警告は表示されません。

int main(void) 
{ 
    void *b = (void *)0x12345678; 
    int a = (int)(unsigned long)b; 
    int c = (int)b; 
    return a + c; 
} 

$ gcc -O3 -g -std=c99 -Wall -Wextra -c ar.c 
ar.c: In function ‘main’: 
ar.c:5:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 
$ 

を64ビットコンパイルをデフォルトのMac OS X 10.8.4上でGCC 4.7.1を使用する:実証するために

'アドレスの一部'の値で何が行われるかを推測することは面白いです。

+2

あなたは創造的な人々が 'void *' sの数値(または論理値)の情報を隠しています:) – hroptatyr

+0

あなたがコメントしている間に書いていたサンプルコードで、 –

+0

Hehe、確かにそれゆえ+1:深刻なことに、多くのAPIは 'void *'を使用します。ここで 'intptr_t'は適切でしょう。 – hroptatyr

0

私もこのプロジェクトを参照してください。

私の場合、 'b'の内容は、プロセス間通信に使用される他のソース/ミドルウェアによって入力されます。

「B」が投入されると、プログラムが正しいフィールド「」へのキャストで「B」の内容を取得します。アプリケーションは処理のために 'a'を使用します。

私のプロジェクトでは、void *の代わりにchar *が使用されています。直接小さいタイプへのポインタに型キャスト

1

はintはx64のビット環境下(クランのような)いくつかのコンパイラでコンパイルエラーになることがあり言います。例えば

void *p = GetSomeAddress; 
int i = (int)p; //error on compilers like Clang. 

溶液である:Unixで、LP64モデルで、長は64ビットであり、これは

int i = (int)(unsigned long)p; 

又は

int i = (int)(long)p; 

このようなケースは、あなたはintへのポインタまたは他の小さいタイプから型キャスト必要とする理由データの損失を生じ得ることを徹底的に調べる必要があります。

この質問はお役に立ちます。 How should I handle "cast from ‘void*’ to ‘int’ loses precision" when compiling 32-bit code on 64-bit machine?

関連する問題