4

C で Pointerを使用する場合、最初のIdentifierrestrictを使用して変数を変更しても問題ありませんか? 例えば:

int foo = 0;

int * restrict fooPtr = &foo;
++(*fooPtr);                   // Part 1: foo is 1 (OK)

++foo;                         // Part 2: foo is 2 (Is this OK?)

int * fooPtr2 = &foo;
++(*fooPtr2);                  // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer)

... fooPtrが作成された後、fooを介してfooの値を変更しました。restrict

パート 1は問題ないように見えます。パート 2について混乱しています。そして、私が理解していることからrestrictパート3は悪いです(コンパイラはそれを許可しますが、その動作は未定義であり、そうしないのはプログラマ次第です)。

4

4 に答える 4

4

いいえ、パート 2 は問題ありません。

標準の特定の部分は 6.7.3.1/4 です。このセクションは非常に密集しており、数回の再読み取りが必要ですが、P は制限ポインターであり、X はアクセスに使用され、変更されるオブジェクトです。したがって、あなたの例では P はfooPtrであり、X はfooです。それで:

X の値にアクセスするために使用される他のすべての左辺値も、P に基づくアドレスを持つものとします。

「に基づく」は前の段落で定義されており、要約すると、左辺値は制限ポインター P に基づくアドレスを持ってfooいませfoo。そのため、オブジェクト自体の名前を介してオブジェクトにアクセスすると、ルールが破られます。

パート 3 はまったく同じ理由で OK ではありません。左辺値*fooPtr2は P にも基づいていませんが、X へのアクセスにも使用されます。

私は「大丈夫ではない」と言います - 正確には、1+2 の組み合わせは、1+3 の組み合わせと同様に、未定義の動作を引き起こします。制限ポインターを介して実際にオブジェクトにアクセスしない限り、制限の定義はどれも「開始」されません。必要に応じて、パート 1 を削除し、未使用の制限ポインターを保持してから、2 と 3 で問題ありません。

于 2010-10-14T18:08:31.787 に答える
1

#2が悪いと思います。たとえば、コンパイラーは *fooPtr の値をレジスターにロードして最適化し、後でそのレジスター値を再び foo に書き戻す可能性があります (++foo の後で、++foo が失われるようにするため)。

于 2010-10-14T18:09:25.077 に答える
1

はい、「パート 3」は未定義の動作です。C99 仕様 (6.7.3、パラグラフ 7) から:

制限修飾されたポインターを介してアクセスされるオブジェクトは、そのポインターとの特別な関連付けを持っています。以下の 6.7.3.1 で定義されているこの関連付けでは、そのオブジェクトへのすべてのアクセスで、直接的または間接的に、その特定のポインターの値を使用する必要があります。

于 2010-10-14T18:04:55.193 に答える
1

質問のすべての部分が同じブロックで発生すると仮定すると、の値にfoo直接アクセスすること (パート 2) も、別のポインターを介してアクセスすること (パート 3) も問題ありません。

  • 6.7.3.1 restrict の正式な定義

X の値にアクセスするために使用される他のすべての左辺値も、P に基づくアドレスを持つものとします。

の正式な定義にrestrict従うのは非常に困難です (少なくとも私にとってはそうです) が、標準からの次のあまり正式でない説明も (少なくともこの場合) かなりうまくまとめられています。

制限修飾ポインターを介してアクセスされるオブジェクトには、そのポインターとの特別な関連付けがあります。以下の 6.7.3.1 で定義されているこの関連付けでは、そのオブジェクトへのすべてのアクセスで、直接的または間接的に、その特定のポインターの値を使用する必要があります。

于 2010-10-14T18:11:37.850 に答える