web-dev-qa-db-ja.com

ポインター演算:++ * ptrまたは* ptr ++?

私はC言語を学習していて、++*ptrおよび*ptr++

例えば:

int x = 19;
int *ptr = &x;

知っている ++*ptrおよび*ptr++異なる結果が生成されますが、それはなぜですか?

20
ipkiss

これらのステートメントは、演算子のバインド方法が原因で、異なる結果を生成します。特に、接頭辞++演算子の優先順位は*と同じであり、右から左に関連付けられます。したがって

++*ptr

として解析されます

++(*ptr)

ptrが指す値を増やす」という意味です。一方、postfix++演算子は、逆参照演算子*よりも優先されます。その前に

*ptr++

手段

*(ptr++)

これは、「ptrが現在指している値に評価し、ptrの値をインクリメントする」ことを意味します(その順序は指定されていません)。

あなたが説明したコンテキストでは、xを介して間接的にptrをインクリメントする++*ptrを記述したいと思うでしょう。 *ptr++を書き込むと、ptrxを越えて進むので危険です。また、xが配列の一部ではないため、ポインターはメモリ内のどこかに(おそらくそれ自体の上に)ぶら下がっています。

お役に立てれば!

47
templatetypedef

受け入れられた答えは正しくありません。接尾辞_++_演算子の優先順位が逆参照/間接参照_*_と同じであるとは限りません。前置演算子と後置演算子の優先順位は異なり、prefix演算子のみが逆参照/間接参照と同じ優先順位を持ちます。

優先順位テーブル が示すように、postfix _++_は、間接参照/間接参照_*_よりも高い優先順位を持っています。したがって、_*ptr++_は*(ptr++)として評価されます。 _ptr++_はptrの現在の値に評価されます。副作用としてのみptrをインクリメントします。式の値は、ptrの現在の値と同じです。したがって、ポインタに格納されている値には影響しません。それは単にポインタを逆参照する(つまり、そこに格納されている現在の値(19)を取得する)してから、ポインタを進めます。あなたの例では、ptrの新しい位置に定義された値が格納されていないため、ポインターはガベージを指しています。今それを逆参照するのは危険です。

また、表に示されているように、接頭辞_++_は逆参照/間接参照_*_と同じ優先順位を持っていますが、左右の結合性のため、++(*ptr)として評価されます。これは最初にポインターを逆参照し(つまり、ポイントされたアドレスに格納されている値を取得し)、次にその値をインクリメントします。つまり、値は20になります。

受け入れられた答えは2つの効果については正しいですが、実際のメカニズムはそこで与えられたものとは異なります。

8
verbose

Templatetypedefが言うように、結果を確実にするために*ptrを括弧で囲む必要があります。たとえば、次の例では、GCCを使用して1606415888を生成し、私のコンピューターでCLangを使用して0を生成します。

int x = 19;
int *ptr = &x;
printf("%d\n", *ptr++);
printf("%d\n", *ptr);

そして、xが20であると予想しました。代わりに(*ptr)++を使用してください。

4