Cで制限ポインターを使用する場合、初期識別子を使用して変数を変更しても構いませんか?

StackOverflow https://stackoverflow.com/questions/3936060

  •  30-09-2019
  •  | 
  •  

質問

使用する場合 restrict cのポインター、その初期を使用して変数を変更しても構いませんか 識別子?例えば:

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)

...の価値を変更しました foo 終えた foo 後に restrict fooptr 作成されました。

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

役に立ちましたか?

解決

いいえ、パート2は大丈夫ではありません。

標準の特定の部分は6.7.3.1/4です。このセクションはかなり密度が高く、いくつかの再読み取り値を取得しますが、Pは制限ポインターであり、Xはアクセスに使用され、変更されるオブジェクトです。したがって、あなたの例ではpはそうです fooPtr とxは foo. 。それで:

Xの値にアクセスするために使用される他のすべてのLValueは、Pに基づいてアドレスも持たなければならない。

「ベース」は前の段落で定義されており、要約するために、lvalue foo します いいえ 制限ポインターPに基づいてアドレスを持っているので、オブジェクトにアクセスするとルールが壊れます foo 独自の名前を通して。

パート3はまったく同じ理由で問題ありません、lvalue *fooPtr2 Pにも基づいていませんが、Xにアクセスするためにも使用されます。

私は「OK」と言います - 正確に言うと、1+2の組み合わせは、1+3の組み合わせと同様に未定義の動作を引き起こします。制限ポインターを介して実際にオブジェクトにアクセスしない限り、制限「キックイン」の定義はどれもありません。必要な場合は、パート1を削除することができます。未使用の制限ポインターを保持してください。そうすれば、2と3が問題ありません。

他のヒント

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

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

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

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

  • 6.7.3.1制限の正式な定義

Xの値にアクセスするために使用される他のすべてのLValueは、Pに基づいてアドレスも持たなければならない。

の正式な定義 restrict 従うのは非常に困難です(少なくとも私にとってはそうです)が、標準からの以下の少ない説明は、それをかなりよく合計しています(少なくともこの場合は):

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top