1

値が 0x5 の int へのポインターがあるとします。その値に 0x3 のオフセットを追加します。

このようにする必要がありますか(方法A):

int* pointer = 0x5;
int offset = 0x3;

pointer = pointer + (offset/sizeof(int)); // pointer is now equal to 0x8

またはこのように(方法B):

uintptr_t pointer = 0x5;
pointer = pointer + 0x3;

int* ptr = (int*) pointer; // pointer is now equal to 0x8

この質問を見た後、私はこれを尋ねます:uintptr_tデータ型とは何ですか

通常の整数を使用せず、ポインターであるふりをするように通知されました。

4

3 に答える 3

2

uintptr_tポータブルな方法で aに対して演算を実行することはできません。その型の定義方法は次のとおりです。

7.18.1.4 オブジェクトポインタを保持できる整数型

次の型は、void への任意の有効なポインターをこの型に変換してから void へのポインターに戻すことができるというプロパティを持つ符号付き整数型を指定します。結果は元のポインターと等しくなります。

intptr_t

次の型は、void への任意の有効なポインターをこの型に変換し、その後 void へのポインターに戻すことができるプロパティを持つ符号なし整数型を指定します。結果は元のポインターと等しくなります。

uintptr_t

これらのタイプはオプションです。

仕様では、ポインタの表現方法について何も述べていないことに注意してください。ほとんどの実装では、uintptr_t値の算術演算はおそらく期待どおりの結果をもたらしますが、コードを移植可能にしたい場合は、セマンティクスが明確に指定されているポインター演算を使用する必要があります。

uintptr_t演算が予期しない動作をする可能性があるプラットフォームの例は、 IBM の z/OS です。従来の 31 ビット モード (はい、31) では、最上位ポインター ビットはシステム用に予約されています。2 つのポインターがaありb、そのビットのみが異なる場合、それらのポインターを と比較するとa==b、予想どおり 1 (真) が返され、それらを で減算するとa-b0が返されuintptr_tます==-0 以外を返します。

于 2013-10-20T11:26:31.493 に答える
1

char *通常、ここでまたはにキャストしunsigned char *て算術演算を行います。sizeof(char)==1定義により、実際には「通常の」算術演算を行うことになるため、「ポインター ドメイン」を決して離れないという利点があります。エイリアシング規則に違反しています。

于 2013-10-20T02:02:49.943 に答える
1
int *pointer = 0x5;
int offset = 0x3;
pointer = pointer + (offset/sizeof(int));

を仮定するとsizeof(int) == 4、除算は 0 に評価され、ポインターは変更されません。で割り切らなかった場合sizeof(int)、ポインターは単位で進み3*sizeof(int) charます。

uintptr_t pointer = 0x5;
pointer = pointer + 0x3;
int *ptr = (int *) pointer;

これは、実際ptrには同じ値に設定されptr = (int *)0x8ます。(これは何かへの有効なポインターではない可能性が圧倒的に高いです。)

上記のいずれも、 C でこの種のことを行う通常の方法ではありませんchar *

int *pointer = 0x5;
ptrdiff_t offset = 0x3;
pointer = (int *) (((char *)pointer) + offset);
assert (pointer == (int *)0x8);
于 2013-10-20T02:03:03.537 に答える