53

使用との使用について質問がありintptr_tますlong int。メモリアドレスのインクリメント(手動ポインタ演算など)はデータ型によって異なることを確認しました。たとえば、charポインタをインクリメントするとメモリアドレスに1が追加され、intポインタをインクリメントするとdoubleの場合は4、8、longdoubleの場合は16などが追加されます。

最初、私はこのようなことをしました:

char myChar, *pChar;
float myFloat, *pFloat;

pChar = &myChar;
pFloat = &myFloat;

printf( "pChar:  %d\n", ( int )pChar );
printf( "pFloat: %d\n", ( int )pFloat );

pChar++;
pFloat++;

printf( "and then after incrementing,:\n\n" );
printf( "pChar:  %d\n", (int)pChar );
printf( "pFloat:    %d\n", (int)pFloat );

これは正常にコンパイルおよび実行されましたが、XCodeは、型キャストに対して「ポインターから異なるサイズの整数にキャストします」という警告を出しました。

いくつかのグーグルとビンビンの後(後者はまだ言葉ですか?)、私は何人かの人々が使用を勧めるのを見ましたintptr_t

#include <stdint.h>

..。

printf( "pChar:  %ld\n", ( intptr_t )pChar );
printf( "pFloat: %ld\n", ( intptr_t )pFloat );

これは確かにエラーを解決します。だから、これからはポインタの型キャストに使うべきだと思ったのですが…でも、そわそわした後、次のように置き換えるだけでintptr_t問題を解決できることがわかりました。intlong int

printf( "pChar:  %ld\n", ( long int )pChar );
printf( "pFloat: %ld\n", ( long int )pFloat );

だから私の質問は、なぜintptr_t有用なのか、そしていつそれを使うべきなのかということです。この場合は不要のようです。明らかに、メモリアドレスmyCharmyFloatは大きすぎて収まりませんでしたint...したがって、それらを型キャストしてlong int問題を解決しました。

メモリアドレスが大きすぎることもありますlong intか?今考えてみると、RAMが4GBを超える場合は可能だと思います。その場合、メモリアドレスは2 ^ 32-1(unsigned long intの最大値...)を超える可能性がありますが、Cはそれよりずっと前に作成されました。想像できますよね?それとも彼らはその先見の明がありましたか?

ありがとう!

4

4 に答える 4

56

intptr_tは、64ビットおよび128ビットのメモリアドレスが想像された後に作成された新しい発明です。

ポインタを整数型にキャストする必要がある場合は、常に。使用してintptr_tください。他のことをすると、将来コードを移植する必要がある人にとって不必要な問題が発生します。

人々が64ビットLinuxでコンパイルしたいときに、Mozilla/Firefoxのようなプログラムでこれに関するすべてのバグを解決するのに長い時間がかかりました。

于 2011-06-13T03:21:49.817 に答える
43

ここに問題があります: 一部のプラットフォームでintは適切なサイズですが、他のプラットフォームではlong適切なサイズです。どちらを使用する必要があるかをどのように知ることができますか? あなたはそうしない。どちらかが正しいかもしれませんが、標準ではどちらが正しいかは保証されていません (どちらかである場合)。したがって、標準では、使用しているプラ​​ットフォームに関係なく、正しいサイズであると定義された型が提供されます。以前はどこに書く必要があったか:

#ifdef PLATFORM_A
  typedef long intptr;
#else
  typedef int intptr;
#endif

今、あなたは書くだけです:

#include <stdint.h>

そして、それは非常に多くのケースをカバーしています。コードが実行されるすべてのプラットフォームに上記のスニペットを特化することを想像してみてください。

于 2011-06-13T04:05:26.337 に答える
11

1つ目は、 intptr_t(関数ではなく) データ ポインター専用であり、存在することが保証されていません。

いいえ、印刷目的で使用しないでください。その%pためです。ポインターをキャストするだけで(void*)、そこに行くことができます。

また、算術/個々のバイトへのアクセスにも適していません。代わりにキャストし(unsigned char*)ます。

intptr_tポインタを整数として解釈しなければならないまれなケースのためのものです (実際にはそうではありません)。する必要がない場合は、それをしないでください。

于 2011-06-13T09:29:04.683 に答える
11

p変換指定子を使用すると、作業が楽になります。

printf("%p\n", (void *)foo);

また、型の変数を表示する移植可能な方法は、 のマクロ(u)intptr_tを使用することです。以下は、私のプラットフォーム (32 ビット) で使用する場合と同等です。PRI*PTRinttypes.hp

printf("%08" PRIxPTR "\n", (uintptr_t)(void *)foo);

へのキャストvoid *は完全な移植性のために必要ですが、統一されたポインター表現を持つプラットフォームでは省略できます。

于 2011-06-13T09:32:45.233 に答える