volatile
新しい値が更新されるたびに変数を宣言する場合変数をとして
宣言するconst
場合、その変数の値は変更されません
それでは、上記のようにconst volatile int temp;
変数を宣言することの使用法は何temp
ですか?
として宣言するとconst int temp
どうなりますか?
volatile
新しい値が更新されるたびに変数を宣言する場合変数をとして
宣言するconst
場合、その変数の値は変更されません
それでは、上記のようにconst volatile int temp;
変数を宣言することの使用法は何temp
ですか?
として宣言するとconst int temp
どうなりますか?
回答:
としてマークされたオブジェクトはconst volatile
、コードによる変更が許可されません(const
修飾子が原因でエラーが発生します)-少なくともその特定の名前/ポインターを介して。
volatile
修飾子の一部は、コンパイラーがオブジェクトへのアクセスを最適化または並べ替えることができないことを意味します。
組み込みシステムでは、これは通常、ハードウェアによって読み取りおよび更新できるハードウェアレジスタにアクセスするために使用されますが、書き込みには意味がありません(または書き込みエラーになる可能性があります)。
例として、シリアルポートのステータスレジスタがあります。さまざまなビットは、文字が読み取られるのを待っているかどうか、または送信レジスタが新しい文字を受け入れる準備ができているかどうか(つまり、空であるかどうか)を示します。このステータスレジスタを読み取るたびに、シリアルポートハードウェアで他に何が発生したかによって、異なる値になる可能性があります。
(特定のハードウェア仕様に応じて)ステータスレジスタに書き込むことは意味がありませんが、レジスタの各読み取りがハードウェアの実際の読み取りになることを確認する必要があります-前の読み取りからのキャッシュ値を使用して ' tハードウェア状態の変化について教えてください。
簡単な例:
unsigned int const volatile *status_reg; // assume these are assigned to point to the
unsigned char const volatile *recv_reg; // correct hardware addresses
#define UART_CHAR_READY 0x00000001
int get_next_char()
{
while ((*status_reg & UART_CHAR_READY) == 0) {
// do nothing but spin
}
return *recv_reg;
}
これらのポインタがであるとマークされていない場合volatile
、いくつかの問題が発生する可能性があります。
*recv_reg
ループによって変更されたことを示す関数には何もないため、ループに入る前に読み取ることができない理由はありません。volatile
これらの最適化は、コンパイラによって実行されていないことを修飾子を確実にします。
volatile
変数に関連するコードを最適化しないようにコンパイラーに指示します。通常は、別のスレッドなどによって「外部」から変更できることがわかっている場合です。const
プログラムが変数の値を変更することは禁止されていることをコンパイラーに通知します。const volatile
これは非常に特別なことであり、おそらくあなたの人生(tm)で正確に0回使用されていることがわかります。当然のことながら、プログラムは変数の値を変更できませんが、値は外部から変更できるため、変数に対して最適化は実行されません。volatile
変数は通常、他のスレッドではなく、ハードウェアをいじり始めたときに起こることだと思いました。私がconst volatile
使用しているのは、メモリマップドステータスレジスタなどです。
変数がconstであるため、2つのシーケンスポイント間で変更されていない可能性があります。
恒常性とは、値が変更されないということではなく、値を変更しないという約束です。
const
データが「一定」ではない。
ブートローダーで更新できるフラッシュメモリの領域にいくつかの構成変数が配置されている組み込みアプリケーションでこれを使用する必要がありました。これらの構成変数は実行時に「一定」ですが、揮発性修飾子がないと、コンパイラーは次のようなものを最適化します...
cantx.id = 0x10<<24 | CANID<<12 | 0;
...定数値を事前計算して即時アセンブリ命令を使用するか、近くの場所から定数をロードして、構成フラッシュ領域の元のCANID値への更新が無視されるようにします。CANIDはconstvolatileである必要があります。
Cでは、constとvolatileは型修飾子であり、これら2つは独立しています。
基本的に、constは、値がプログラムによって変更できないことを意味します。
また、揮発性とは、値が突然変更される可能性があることを意味します(おそらくプログラムの外部から)。
実際、C標準では、constとvolatileの両方である有効な宣言の例に言及しています。例は
「externconstvolatile intreal_time_clock;」
ここで、real_time_clockはハードウェアによって変更可能ですが、割り当て、インクリメント、またはデクリメントすることはできません。
したがって、constとvolatileを別々に扱う必要があります。さらに、これらの型修飾子は、struct、union、enum、およびtypedefにも適用されます。
const
変数が変更できないということではなく、cコードで変数を変更できないことを意味します。これは、命令が変数に書き込むことができないが、その値が変更される可能性があることを意味します。
volatile
変数はいつでも変更される可能性があるため、キャッシュされた値は使用されない可能性があることを意味します。変数への各アクセスは、そのメモリアドレスに対して実行する必要があります。
質問には「埋め込み」のタグが付けられているので、 temp
、ハードウェア関連のレジスタではなく、ユーザーが宣言した変数であるいるため(これらは通常、別の.hファイルで処理されるため)、次のことを考慮してください。
揮発性の読み取り/書き込みデータメモリ(RAM)と不揮発性の読み取り専用データメモリの両方を備えた組み込みプロセッサ。たとえば、データとプログラムスペースが共通のデータとアドレスバスを共有するフォンノイマンアーキテクチャのフラッシュメモリ。
あなたが宣言した場合 const temp
値を持つした場合(少なくとも0と異なる場合)、コンパイラは変数をFLASHスペースのアドレスに割り当てます。これは、RAMアドレスに割り当てられた場合でも、初期値を格納するためにFLASHメモリが必要になるためです。すべての操作が読み取り専用であるため、RAMアドレスをスペースの浪費にします。
結果として:
int temp;
RAMに格納されている変数で、起動時(cstart)に0に初期化され、キャッシュされた値を使用できます。
const int temp;
(read-ony)FLASHに格納され、コンパイラ時に0に初期化される変数であり、キャッシュされた値を使用できます。
volatile int temp;
RAMに格納され、起動時に0に初期化される変数(cstart)であり、キャッシュされた値は使用されません。
const volatile int temp;
(read-ony)FLASHに格納され、コンパイラ時に0に初期化される変数であり、キャッシュされた値は使用されません
ここに便利な部分があります:
現在、ほとんどの組み込みプロセッサには、特別な汎用モジュールを使用して読み取り専用の不揮発性メモリを変更する機能があります。この場合const int temp
、直接ではなく、実行時に変更できます。別の言い方をすれば、関数temp
は、格納されているアドレスの値を変更する場合があります。
実用的な例はtemp
、デバイスのシリアル番号に使用することです。組み込みプロセッサが最初に実行temp
されるときは、0(または宣言された値)に等しくなり、関数はこのファクトを使用して本番環境でテストを実行し、成功した場合はシリアル番号の割り当てを要求し、の値を変更します。temp
によって特別な機能の。一部のプロセッサには、そのためだけにOTP(ワンタイムプログラマブル)メモリを備えた特別なアドレス範囲があります。
しかし、ここに違いがあります。
場合はconst int temp
、変更IDの代わりに、ワンタイムプログラマブルシリアル番号であると宣言されていないvolatile
、キャッシュされた値は、新しいIDは、次の再起動、またはさらに悪いことに、いくつかの機能の有効なそれまではないかもしれないという意味、それまでは次の起動時に使用されるかもしれません再起動するまで、新しい値を使用する場合もあれば、古いキャッシュ値を使用する場合もあります。場合const int temp
ISが宣言voltaile
、IDの変更はすぐに反映されます。
この記事では、const修飾子とvolatile修飾子を組み合わせるシナリオについて説明します。
http://embeddedgurus.com/barr-code/2012/01/combining-cs-volatile-and-const-keywords/
const volatile int temp;
ブロックスコープ(すなわち内部に{ }
それはそこには、使用を持っていません、)。