GNU Cの__attribute__((const))
と__attribute__((pure))
の違いは何ですか?
__attribute__((const)) int f() {
/* ... */
return 4;
}
対
__attribute__((pure)) int f() {
/* ... */
return 4;
}
違いは GCCマニュアル で説明されています。最も重要なのは、const
関数は渡された引数のみを使用し、メモリは使用しないことです。一方、pure
関数は、制約の下でもメモリにアクセスできます。
純粋属性は、関数が関数の戻り値を検査する以外の方法で観察できるプログラムの状態を変更することを禁止します。ただし、pure属性で宣言された関数は、すべての不揮発性オブジェクトを安全に読み取り、戻り値やプログラムの監視可能な状態に影響を与えない方法でオブジェクトの値を変更できます。
__attribute__ ((pure))
は、関数に副作用がなく、返される値が引数とグローバル変数の状態に依存することを意味します。したがって、引数が同じで、呼び出し元が呼び出し間のグローバルの状態を変更するために何もしなかった場合、オプティマイザが呼び出しを省略しても安全です。
__attribute__ ((const))
は、戻り値が引数の関数のみであることを意味し、引数のいずれかがポインタの場合、ポインタが必須である逆参照されない。
const
関数は常にpure
です。
const
関数の例は、<stdlib.h>
のabs
関数と<math.h>
のいくつかの数学関数です:sqrt
、exp
、など(丸めモードの対象になる場合があります)。
pure
の例ですが、非const関数はstrlen
などの関数です-渡されたポインターを逆参照するためです。
ARMコンパイラ (gccに基づく)のドキュメント)から:
__attribute__((pure))
関数属性
多くの関数は値を返す以外は効果がなく、戻り値はパラメーターとグローバル変数にのみ依存します。この種の関数は、データフロー分析の対象となる可能性があり、削除される可能性があります。
__attribute__((const))
関数属性
多くの関数は渡された引数のみを検査し、戻り値以外の効果はありません。関数はグローバルメモリの読み取りを許可されていないため、これは__attribute__((pure))
よりもはるかに厳密なクラスです。関数がその引数に対してのみ動作することがわかっている場合、その関数は一般的な部分式の削除とループの最適化の対象となる可能性があります。
したがって、TL; DR:__attribute__((const))
は__attribute__((pure))
と同じですが、グローバル変数にアクセスできません。
関数にポインターが渡され、そのポインターのコンテキストを検査する場合、渡されたポインターとポインターコンテキストがconst
であっても、関数をconst
と宣言することはできません。これは、const
の有用性に対する深刻な制限です。
Cでは、構造体を使用して複数の値を返すことができます。これにより、pure
が使いやすくなります。 (ポインターの戻りオペランドを使用する方が一般的ですが、これはpure
の使用を中断します)。