intptr_t
対long int
の使用に関して質問があります。私は、メモリアドレスのインクリメント(たとえば、手動ポインタ演算による)がデータ型によって異なることを観察しました。たとえば、charポインタをインクリメントするとメモリアドレスに1が加算されますが、intポインタをインクリメントするとdoubleに4、8、long doubleに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は型キャストに対して「ポインターから異なるサイズの整数へのキャスト」という警告を出しました。
いくつかのグーグルとビンギングの後(後者はまだWordですか?)、一部の人々がintptr_t
の使用を推奨するのを見ました:
#include <stdint.h>
...
printf( "pChar: %ld\n", ( intptr_t )pChar );
printf( "pFloat: %ld\n", ( intptr_t )pFloat );
実際にエラーを解決します。ですから、今後、型キャストポインタにintptr_t
を使用する必要があると考えました...しかし、少し調整した後、int
をlong int
に置き換えるだけで問題を解決できることがわかりました。
printf( "pChar: %ld\n", ( long int )pChar );
printf( "pFloat: %ld\n", ( long int )pFloat );
だから私の質問は、なぜintptr_t
が便利で、いつ使用する必要があるのかということです。この例では不要なようです。明らかに、myChar
とmyFloat
のメモリアドレスが大きすぎてint
...に収まらないので、それらをlong int
sに型キャストすると問題が解決しました。
long int
に対してもメモリアドレスが大きすぎる場合がありますか?考えてみると、4 GBを超えるRAMがあれば可能だと思います。この場合、メモリアドレスは2 ^ 32-1(符号なしlong intの最大値...)を超える可能性がありますが、Cはずっと前に作成されました想像できるでしょう?それとも、それらは先見の明がありましたか?
ありがとう!
これは、一部のプラットフォームではint
が適切なサイズですが、他のプラットフォームではlong
が適切なサイズです。どれを使用すべきかをどのようにして知るのですか?あなたはしません。 1つは正しいかもしれませんが、標準は、どちらになるかについて保証しません(どちらかである場合)。そのため、標準では、使用しているプラットフォームに関係なく、正しいサイズであると定義されたタイプが提供されます。あなたが書く必要があった前の場所:
#ifdef PLATFORM_A
typedef long intptr;
#else
typedef int intptr;
#endif
今、あなたは書くだけです:
#include <stdint.h>
そして、さらに多くのケースをカバーしています。 すべての単一プラットフォームでコードを実行するために上記のスニペットを特化することを想像してください。
intptr_t
は、64ビットおよび128ビットのメモリアドレスが想像された後に作成された新しい発明です。
everポインタを整数型にキャストする必要がある場合、always use intptr_t
。他に何かをすることは、将来あなたのコードを移植する必要がある人々にとって不必要な問題を引き起こすでしょう。
人々が64ビットLinuxでコンパイルしたいと思ったとき、Mozilla/Firefoxのようなプログラムでこれに関するすべてのバグを解決するのに長い時間がかかりました。
まず、intptr_t
はデータポインター専用であり(関数ではない)、存在が保証されていません。
それから、いや、印刷の目的でそれを使うべきではありません。 %p
はそのためのものです。ポインタを(void*)
にキャストするだけです。
また、算術/個々のバイトへのアクセスにも適していません。代わりに(unsigned char*)
にキャストしてください。
intptr_t
は、ポインターを整数として解釈しなければならないまれな場合のためです(実際にはそうではありません)。する必要がない場合は、そうしないでください。
p
変換指定子を使用すると、生活が楽になります。
printf("%p\n", (void *)foo);
また、タイプ(u)intptr_t
の変数を印刷するポータブルな方法は、PRI*PTR
のinttypes.h
マクロを使用することです。以下は、私のプラットフォーム(32ビット)でp
を使用するのと同等です。
printf("%08" PRIxPTR "\n", (uintptr_t)(void *)foo);
void *
へのキャストは完全な移植性のために必要ですが、統一されたポインター表現を持つプラットフォームでは省略できます。