1

組み込み SW プロジェクトの場合、いくつかのconst volatile TYPE *ポインターを使用する必要があります。これで、次のような計算関数がいくつかあります。

uint8 calc(const volatile uint8 *array, uint8 value) { ... }

両方の変数のデータは、関数の実行中に変化しません。

呼び出しコードは次のようになります。

const volatile uint8 *array = (const volatile uint8 *)0x00010111;
uint8 value = 8;

uint8 result = calc(array, value);

問題は、揮発性引数なしで計算関数を設計した場合、違いがあるかどうかです。

uint8 calc(const uint8 *array, uint8 value) { ... }

呼び出しでは、volatile をキャストします。

uint8 result = calc((const uint8 *)array, value);

2 番目のソリューションの長所は、柔軟性が高いことです。この関数は、非揮発性変数にも使用できます。しかし、揮発性をキャストし、コンパイラがいくつかの強力な最適化を行った場合、違いはありますか?

4

3 に答える 3

3

この関数は、常に非揮発性引数とともに使用できます。関数内のコードが、指定されたオブジェクトを揮発性であるかのように処理するだけです (途中でパフォーマンスが低下する可能性が最も高い)。揮発性の引数を持つ関数 (「通知なしに変更される可能性があるため」) が賢明にできることを想像するのは少し難しいです。あなたが書いているように、あなたの場合、データはとにかく変更されないので、最も柔軟な解決策は、パラメーター const を宣言し、volatile を忘れることです。

uint8 のような自家製の型名ではなく、「uint8_t」を使用してください。1996 年から標準になっています。

于 2012-12-07T12:46:52.087 に答える
1

2 つのケースがあります。関数がハードウェア レジスタなどを直接操作している場合です。次に、パラメーターに volatileが必要です。または、関数はハードウェアレジスタとはまったく関係ありません。次に、揮発性を持つべきではありません。これら 2 つのケースの間に中間点はありません。

さらに、calc((const uint8_t*)array, value);単に悪い、おそらくバグのあるバージョンです

const uint8_t* ptr = array;
calc(ptr, value);

関数の引数の評価順序が規定されていないため、前者の形式は不適切です。コンパイラは、左オペランドまたは右オペランドを最初に評価することを選択する場合があり、順序を知ることも推測することもできません。volatile へのアクセスは副作用であるため、元のコードはプログラムがビルドされるたびに異なる結果をもたらす可能性があります。これは、リアルタイムの組み込みシステムでは特に問題になります (そしておそらく危険です)。

したがって、式内の volatile 変数にアクセスしないことをお勧めします (MISRA-C:2004 12.2 を参照)。

于 2012-12-07T14:03:29.400 に答える
0

volatileそれは、 -nessによって実際に何が起こるかによって異なります。

関数の実行中にこの配列の値が変更され、これらの変更に気付く必要がある場合は、それらをvolatile.

問題がない場合、または「古い」値の方が重要な場合は、. を省略しvolatileます。

于 2012-12-07T12:27:05.553 に答える