検索
ホームページバックエンド開発C#.Net チュートリアルC言語のvolatileキーワードの機能は何ですか?

C言語のvolatileキーワードの機能は何ですか?

Oct 30, 2020 pm 03:02 PM
C言語不安定なキーワード

C 言語における volatile キーワードの役割: 後で定義された変数がいつでも変更される可能性があることをコンパイラに思い出させるため、コンパイルされたプログラムでこの変数を保存または読み取る必要があるたびに、そのことをコンパイラに伝えます。この変数が最適化されていない場合、データは変数メモリ アドレスから直接読み取られるため、特別なアドレスへの安定したアクセスが提供され、エラーが回避されます。

C言語のvolatileキーワードの機能は何ですか?

#チュートリアルの推奨事項: 「

c 言語チュートリアル ビデオ

1. はじめに

1. コンパイラの最適化の概要:

メモリ アクセス速度は CPU の処理速度に比べてはるかに遅いため、コンパイラの最適化を改善するにはハードウェアにおけるマシンの全体的なパフォーマンス ハードウェア キャッシュ キャッシュを導入して、メモリへのアクセスを高速化します。また、現代の CPU では命令の実行が必ずしも厳密な順序に従っているわけではなく、CPU の命令パイプラインを最大限に活用して実行速度を向上させるために、相関関係のない命令を順不同で実行することもできます。上記はハードウェアレベルの最適化です。ソフトウェア レベルの最適化を見てみましょう。1 つはコードを記述するときにプログラマによって最適化され、もう 1 つはコンパイラによって最適化されます。 コンパイラの最適化に一般的に使用される方法には、メモリ変数をレジスタにキャッシュする、CPU 命令パイプラインを最大限に活用するために命令の順序を調整するなどがあります。一般的な方法は、読み取り命令と書き込み命令の順序を変更することです。従来型メモリを最適化する場合、これらの最適化は透過的で非常に効率的です。コンパイラの最適化またはハードウェアの並べ替えによって引き起こされる問題の解決策は、ハードウェア (または他のプロセッサ) の観点から特定の順序で実行する必要がある操作の間にメモリ バリアを配置することです。Linux はマクロ ソリューションを提供します。コンパイラの実行順序の問題。

void Barrier(void)

この関数は、メモリ バリアを挿入するようにコンパイラに通知しますが、ハードウェアでは無効です。コンパイルされたコードは、現在の CPU レジスタ内のすべての変更された値をメモリに保存しますこれらが必要です データが必要な場合は、再度メモリから読み出します。

2. Volatile は常に最適化に関係しており、コンパイラにはデータ フロー分析と呼ばれる技術があり、プログラム内の変数がどこに割り当てられ、どこで使用され、どこで変数が使用されているかを分析します。失敗と分析結果 定数のマージ、定数の伝播、その他の最適化に使用でき、さらに一部のコードを削除できます。ただし、プログラムによってはこれらの最適化が必要ない場合もあります。この場合、 volatile キーワードを使用してこれらの最適化を禁止できます。

##2. volatile の詳細説明: ##1. 原理と機能:

#Volatile の本来の意味は「揮発性」です。レジスタへのアクセスはメモリ ユニットへのアクセスよりもはるかに高速であるため、一般にコンパイラはメモリへのアクセスを減らすために最適化を実行しますが、ダーティ データが読み取られる可能性があります。

volatile を使用して変数値を宣言する必要がある場合 、システムは常にデータが配置されているメモリからデータを再読み取りします

。前の命令はそこからそれを読み取るだけです データは読み取られました。

正確には、このキーワードで宣言された変数が見つかった場合、コンパイラはその変数にアクセスするコードを最適化しなくなります (データは変数のメモリ アドレスから直接読み取られます)。これにより、特別なアドレスへの安定したアクセスが提供され、volatile が使用されない場合、コンパイラは宣言されたステートメントを最適化します。 (簡単に言えば、volatile キーワードはコンパイラの結果に影響します。volatile で宣言された変数は、変数がいつでも変更される可能性があることを意味します。エラーを避けるために、変数に関連する操作に対してコンパイルの最適化を実行しないでください)

2. 2 つの例を見てください:

1>

コンパイラ に最適化を行わないよう指示しますたとえば、2 つの命令を特定のアドレスに送信する場合:

int *ip =...; //设备地址 
*ip = 1; //第一个指令 
*ip = 2; //第二个指令

上記のプログラム コンパイラは最適化される可能性があります。

int *ip = ...; 
*ip = 2;
#結果として、最初の命令が失われます。 volatile を使用すると、コンパイラーは最適化を実行できなくなり、プログラムの本来の意図が保証されます。

volatile int *ip = ...; 
*ip = 1; 
*ip = 2;

コンパイラーに最適化を実行させたい場合でも、価値明細書は 1 回に減ります。他の最適化のみが可能です。

2>

volatile

で定義された変数はプログラムの外部で変更されるため、毎回メモリから読み取る必要があり、読み込むことはできません。キャッシュまたはレジスタに配置されたバックアップを再利用します。 ###############例えば:#########

volatile char a;
a=0;
while(!a){
//do some things;
}
doother();

如果没有 volatiledoother()不会被执行

3.下面是使用volatile变量的几个场景:

1>中断服务程序中修改的供其它程序检测的变量需要加volatile;

例如:

static int i=0;
int main(void)
{
     ...
     while (1){
if (i) dosomething();
}
}
/* Interrupt service routine. */
void ISR_2(void)
{
      i=1;
}

程序的本意是希望ISR_2中断产生时,在main函数中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。如果将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

2>多任务环境下各任务间共享的标志应该加volatile

3>存储器映射的硬件寄存器通常也要加voliate,因为每次对它的读写都可能有不同意义。

例如:

假设要对一个设备进行初始化,此设备的某一个寄存器为0xff800000。

int  *output = (unsigned  int *)0xff800000;//定义一个IO端口;
int   init(void)
{
      int i;
      for(i=0;i< 10;i++){
         *output = i;
      }
}

经过编译器优化后,编译器认为前面循环半天都是废话,对最后的结果毫无影响,因为最终只是将output这个指针赋值为9,所以编译器最后给你编译编译的代码结果相当于:

int  init(void)
{
      *output = 9;
}

如果你对此外部设备进行初始化的过程是必须是像上面代码一样顺序的对其赋值,显然优化过程并不能达到目的。反之如果你不是对此端口反复写操作,而是反复读操作,其结果是一样的,编译器在优化后,也许你的代码对此地址的读操作只做了一次。然而从代码角度看是没有任何问题的。这时候就该使用volatile通知编译器这个变量是一个不稳定的,在遇到此变量时候不要优化。

例如:

volatile  int *output=(volatile unsigned int *)0xff800000;//定义一个I/O端口

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中禁止任务调度,3中则只能依靠硬件的良好设计。

4.几个问题

 1)一个参数既可以是const还可以是volatile吗?

可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

2) 一个指针可以是volatile 吗?

可以,当一个中服务子程序修该一个指向一个buffer的指针时。

5.volatile的本质:

1> 编译器的优化

在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。

当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。

当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。

2>volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。

6.下面的函数有什么错误:

int square(volatile int *ptr)
{
return *ptr * *ptr;
}

该程序的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}

注意:频繁地使用volatile很可能会增加代码尺寸和降低性能,因此要合理的使用volatile。

更多编程相关知识,请访问:编程教学!!

以上がC言語のvolatileキーワードの機能は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
C#.NET:コアの概念とプログラミングの基礎を探るC#.NET:コアの概念とプログラミングの基礎を探るApr 10, 2025 am 09:32 AM

C#は、Microsoftによって開発された最新のオブジェクト指向プログラミング言語であり、.NETフレームワークの一部として開発されています。 1.C#は、カプセル化、継承、多型を含むオブジェクト指向プログラミング(OOP)をサポートしています。 2。C#の非同期プログラミングは非同期を通じて実装され、適用応答性を向上させるためにキーワードを待ちます。 3. LINQを使用してデータ収集を簡潔に処理します。 4.一般的なエラーには、null参照の例外と、範囲外の例外インデックスが含まれます。デバッグスキルには、デバッガーと例外処理の使用が含まれます。 5.パフォーマンスの最適化には、StringBuilderの使用と、不必要な梱包とボクシングの回避が含まれます。

テストC#.NETアプリケーション:ユニット、統合、およびエンドツーエンドテストテストC#.NETアプリケーション:ユニット、統合、およびエンドツーエンドテストApr 09, 2025 am 12:04 AM

C#.NETアプリケーションのテスト戦略には、ユニットテスト、統合テスト、エンドツーエンドテストが含まれます。 1.単位テストにより、コードの最小ユニットがMSTEST、ヌニット、またはXUNITフレームワークを使用して独立して動作することを保証します。 2。統合テストでは、一般的に使用されるシミュレートされたデータと外部サービスを組み合わせた複数のユニットの機能を検証します。 3.エンドツーエンドのテストでは、ユーザーの完全な操作プロセスをシミュレートし、通常、セレンは自動テストに使用されます。

高度なC#.NETチュートリアル:次のシニア開発者インタビューをエース高度なC#.NETチュートリアル:次のシニア開発者インタビューをエースApr 08, 2025 am 12:06 AM

C#シニア開発者とのインタビューでは、非同期プログラミング、LINQ、.NETフレームワークの内部作業原則などのコア知識をマスターする必要があります。 1.非同期プログラミングは、非同期を通じて操作を簡素化し、アプリケーションの応答性を向上させるのを待ちます。 2.LinqはSQLスタイルでデータを操作し、パフォーマンスに注意を払います。 3.ネットフレームワークのCLRはメモリを管理し、ガベージコレクションに注意して使用する必要があります。

c#.netインタビューの質問と回答:専門知識を高めるc#.netインタビューの質問と回答:専門知識を高めるApr 07, 2025 am 12:01 AM

C#.NETインタビューの質問と回答には、基本的な知識、コアの概念、高度な使用が含まれます。 1)基本知識:C#は、Microsoftが開発したオブジェクト指向言語であり、主に.NETフレームワークで使用されています。 2)コアの概念:委任とイベントは動的な結合方法を可能にし、LINQは強力なクエリ関数を提供します。 3)高度な使用:非同期プログラミングは応答性を向上させ、式ツリーは動的コード構造に使用されます。

C#.NETを使用したマイクロサービスの構築:建築家向けの実用的なガイドC#.NETを使用したマイクロサービスの構築:建築家向けの実用的なガイドApr 06, 2025 am 12:08 AM

C#.NETは、その強力なエコシステムと豊富なサポートのため、マイクロサービスを構築するために人気のある選択肢です。 1)asp.netcoreを使用してRestfulapiを作成して、順序の作成とクエリを処理します。 2)GRPCを使用して、マイクロサービス間の効率的な通信を実現し、注文サービスを定義および実装します。 3)Dockerコンテナ化されたマイクロサービスを介して展開と管理を簡素化します。

C#.NETセキュリティベストプラクティス:一般的な脆弱性の防止C#.NETセキュリティベストプラクティス:一般的な脆弱性の防止Apr 05, 2025 am 12:01 AM

C#および.NETのセキュリティベストプラクティスには、入力検証、出力エンコード、例外処理、認証と承認が含まれます。 1)正規表現または組み込みのメソッドを使用して入力を検証して、悪意のあるデータがシステムに入るのを防ぎます。 2)XSS攻撃を防ぐための出力エンコード、httputility.htmlencodeメソッドを使用します。 3)例外処理により、情報の漏れが回避され、エラーが記録されますが、詳細情報はユーザーに返されません。 4)ASP.Netidentityおよび請求に基づく許可を使用して、不正アクセスから申請を保護します。

C言語で:それはどういう意味ですかC言語で:それはどういう意味ですかApr 03, 2025 pm 07:24 PM

C言語におけるコロン( ':')の意味:条件付きステートメント:条件付き式とステートメントの分離ブロックループステートメント:初期化、条件付きおよび増分式のマクロ定義の分離:マクロ名とマクロ値の分離単一行コメント:コメントアレイの寸法としてのコロンから行までのコンテンツを表す:アレイの寸法を指定する

C言語では何を意味しますかC言語では何を意味しますかApr 03, 2025 pm 07:21 PM

c言語は、後の運動後演算子であり、その動作メカニズムには次のものが含まれます。最初に変数の値を取得します。 aの値を1 x1。増加した後、aの値を返します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい