3

pは整数ポインターであり、整数であると仮定しますi

*p++に対応する整数値を与えるp

i++1ずつインクリメントされた整数値を与える

動作により、上記の両方が整数を生成するため、 同じエラーが報告されるべきでは++*p++ありませんか? ++i++しかし、 コンパイラ エラーが発生++*p++しているのになぜ機能するの でしょうか。++i++

int main()
{
int a[10] = {0};

int *p = (int*)&a;
int i = 0;

// printf("%d", ++i++); -- FAILS error: lvalue required as increment operand   
printf("%d\n", ++*p++ ); // Prints 1
return 0;
}

編集

++i++ は次のように分解されます。

i++
++(result)

これはまさに私が混乱している場所です: +*p++ を次のように分解できるのと同じ方法で

*p++ 
++(result).

*p++ は、ポインターではなく、値 (右辺値) を返します。では、なぜ違いがあるのでしょうか?

4

2 に答える 2

17

ポストインクリメントの結果は右辺値です。変更することはできません。++i++その右辺値を変更しようとしますが、コンパイラはこれを拒否します。

p++ は右辺値を生成しますが、ポインター型です。変更は許可されていませんが、逆参照は許可されています。*p++その右辺値を逆参照します。これにより、左辺値として、それが指す値が得られます。その後、プレインクリメントは、ポストインクリメントによって生成された右辺値ではなく、それが指す左辺値を変更します。

編集:おそらくもう1つポイントを追加する必要があります。コンパイラによって許可されたとしても、シーケンスポイントを介在させずに2回++i++変更しようとするため、結果は未定義の動作になります。iの場合++*p++、それも起こりません。ポストインクリメントはポインター自体を変更しますが、プレインクリメントはポインターが指すものを (インクリメントされる前に) 変更します。2 つのまったく異なる場所を変更しているため、未定義の動作は発生しません。

どうしてもやりたい場合は、ポインターを初期化してそれ自体を指すようにすることで、未定義の動作が発生する可能性があります。その場合、両方のインクリメントがポインターを変更しようとします。委員会は、これを防止するために懸命に働いていませんでした。おそらく、真に衒学的な人だけが、そのような非常識なことを考える可能性さえあるからです。

結論: この場合、コンパイラはほとんどの場合、自分自身を守ろうとしていますが、十分に努力すれば、それでも自分自身を撃つことができます。

于 2012-06-17T15:24:20.567 に答える
0

++i++次のように分解されます。

i++
++(result)

問題:i++増加できない右辺値、つまり「一時的な」値を返します。これは、インクリメントする前にi++戻るためです。i

于 2012-06-17T15:24:06.857 に答える