5

restrict修飾子を参照して、C11 標準の次の 2 つのセクションに出くわしました。

1#

6.7.3-8

制限修飾ポインターを介してアクセスされるオブジェクトには、そのポインターとの特別な関連付けがあります。以下の 6.7.3.1 で定義されているこの関連付けでは、そのオブジェクトへのすべてのアクセスで、直接的または間接的に、その特定のポインターの値を使用する必要があります。また、適合プログラムを構成するすべての前処理翻訳単位から修飾子のすべてのインスタンスを削除しても、その意味 (つまり、観察可能な動作) は変わりません

筆記体の断片の意味を説明してもらえますか? 私の解釈では、意味が変わらないので、の使用restrictは無意味に見えます...

2#

6.7.3.1-6

翻訳者は、restrict の使用によるエイリアシングの影響の一部またはすべてを自由に無視できます。

これらのエイリアシングの意味は何でしょうか? いくつかの例を見せてもらえますか?

4

4 に答える 4

8

制限は無意味ではありません。これにより、コンパイラーは、ポインターのエイリアシングが可能である場合に許可されない最適化を行うことができます。たとえば、次の関数:

int foo(int *a, int *b)
{
    *a = 5;
    *b = 6;
    return (*a + *b);
}

この関数は何を返しますか?あなたが言ったなら11、あなたは部分的に正しいだけです。を返さ11ない限りa == b、それは戻ります。その場合、それは12、またはさらに悪いことに、いくつかの値の1つである可能性があるbと部分的にオーバーラップします。正しく動作することを確認するために、コンパイラは次のコードを出力する必要があります。

1) stores 5 to a
2) stores 6 to b
3) loads a into a temporary register
4) adds the temp and 6
5) returns the sum

プログラマーa == bが決して起こらないことを知っている場合は、restrictキーワードを使用して、このケースについて心配したくないことをコンパイラーに伝えることができます。

int foo(int * restrict a, int * restrict b)

この関数用に生成されるコードは次のとおりです。

1) store 5 to a
2) store 6 to b
3) return 11

エイリアシングの問題が発生しないと約束したため、コンパイラは最適化を行うことができました。また、標準によれば、コンパイラがrestrictキーワードを無視することを選択した場合、生成されるコードは、最初のケースでは適合(最適化されていない)コードであり、関心のあるすべてのインスタンスで同じように機能します。

于 2012-08-31T20:41:35.943 に答える
6

最初の引用の筆記体のステートメントは、基本的に次のように述べています。

  • たとえば#define restrict、C コードの意味を変更せずにコードに行を追加することで、restrict キーワードを定義することができます。最適化を怠ったためにコードが少し遅くなる可能性がありますが、すべての場合において、restrict キーワードを使用した場合と同じ決定論的な結果が得られます。

2 番目の段落は、コンパイラが restrict キーワードを自由に無視できることを意味します。そのように簡単です。

于 2012-08-31T18:39:18.850 に答える
2

両方のパラグラフで、「restrict」は最適化のヒントに過ぎず、実装はそれを自由に無視できると述べています。

于 2012-08-31T18:33:14.717 に答える
2

また、適合プログラムを構成するすべての前処理翻訳単位から修飾子のすべてのインスタンスを削除しても、その意味 (つまり、観察可能な動作) は変わりません

これは、適合するプログラムではrestrictキーワードのすべての使用がルールを尊重することを意味するため、キーワードを削除してもプログラムの結果は変わりません。

具体的には、適合プログラムでは、ポインターとして渡されたパラメーターは、restrict他のポインターをエイリアスしませんrestrict。そうしないと、キーワードを削除すると、プログラムの意味が変わる可能性があります。

于 2012-08-31T20:09:07.600 に答える