アプリ版:「スタンプのみでお礼する」機能のリリースについて

はじめまして。
現在C言語を学習しているのですが、現在使用している参考書には
volatile修飾子の説明がほとんどなく、どういった機能なのかが
わかりません。volatile修飾子とはどういうときに使用するものなので
しょうか?できれば、volatileの機能が確認できるような
簡単なサンプルがあればうれしいです。どうかご教授お願いします。

A 回答 (6件)

コンパイラに最適化を行う機能があります。


貴方がプログラムを書いた場合、コンパイラはその利用頻度や利用範囲を元に、変数をCPU内レジスタに割り当てるか、RAMに割り当てるかを決めます。
しかし、変数をレジスタに割り当てられては困る場合があります。
たとえば、ハードウェアの制御レジスタは特定のアドレスをアクセスしてR/Wしなければならないので、メモリ上の変数に置き換えられたり、レジスタに割り当てられては役に立ちません。変数の値を変えてもハードウェアの制御レジスタが書き換わらないのでハードウェアは動作せず、バグになってしまいます。
このような変数にvolatile宣言を行うことで、最適化の対象外であることをコンパイラに伝えるのです。

PCですとドライバソフトを書く場合に必須です。
ファームウェアでも常用します。
    • good
    • 1
この回答へのお礼

kazusone様へ
ご回答ありがとうございました。
誤解を恐れずにいうならば、
変数をコンパイルの最適化の対象外にするということは、
コンパイラの判断で変数をレジスタにおくことによって処理を高速化
すると、変数の値が変化してもその変更内容が反映されくなるので、
反映されるようにするためにvolatileを変数に修飾して、
最適化の対象外にするということでよろしいのでしょうか。

お礼日時:2007/03/06 21:43

規格上, volatile は「処理系の感知しない原因で値が変化することがある」という意味です. で, 結果として「最適化しない」ということになります.


これがどんな効果を持つかというと, volatile がない場合には処理系が「ああ, この変数の値は変化しないね」と判断するとその値をレジスタ (など) にコピーし, いちいちメモリ (など) から読み込まないことがあります. それに対し, volatile が付いているとその変数を参照するたびに必ず値を調べに行きます.
    • good
    • 0
この回答へのお礼

Tacosan様へ
ご回答ありがとうございました。
とてもわかりやすい説明をありがとうございました。
コンパイラが具体的にどういうときに最適化するのかを確認できる
簡単な実行例があればありがたいのですが、どうかご教授お願いします。

お礼日時:2007/03/06 21:52

パソコン上で動かすプログラムを書く人だとあまり使わないかもしれませんね.


ただ, #1の方もおっしゃる様に, ハードウェアに近い分野では必要になる場合もあります.

volatile修飾子がついた変数には最適化が働かなくなります.
たとえば, 次のようなコードがあるとします.

long counter;

printf("a\r\n");
for( counter = 0; counter < 100000; counter++ );
printf("b\r\n");
for( counter = 0; counter < 100000; counter++ );
printf("c\r\n");

上記コードでは, for文で無意味なループを回して無駄時間を作っているつもりです.
a, b, cの間に少しタイムラグができるはずです.
(実際にはとわからないと思いますが)

ただ, 前のコードは実行速度の点でコンパイラから見ても明らかに無駄です.
したがって, コンパイラは次の様な具合にコードを最適化してしまう場合があります. (処理系依存です)

long counter;

printf("a\r\n");
printf("b\r\n");
printf("c\r\n");
counter = 100000;

処理が終わった時点では最初のコードと最適化後のコードは同じ事ですが,
無駄処理で時間稼ぎをしていた部分が無くなってしまいました.
処理速度向上といえばそうですが, これでは困ります.
(なお, counter変数を後で使わない場合は変数の存在自体が無かった事にされたりもします)

そんな時に, counter変数の宣言時にvolatileをつけて
volatile int counter;
といった具合にすると, counter変数に関連する処理は最適化の対象外となるため,
プログラマが書いたとおりに動作するようになります.

なお, 先のコードは説明の為のコードであまり意味がありませんが,
実際だと「メモリマップドI/O」(メモリの特定のところにデータを書き込むと
ハードウェア的に何らかの動作が起こる仕組み)
などをいじる時はvolatile修飾子が必須となります.
    • good
    • 1
この回答へのお礼

likipon様へ
ご回答ありがとうございました。
わかりやすい説明とサンプルを示していただきありがとうございました。やっとvolatileの意味が理解できました。
ウチの開発環境で、volatileの有無で動作にどのような違いがあるのかを試してみたところはっきりと違いがあらわれたので確認することが
できました。ありがとうございました。

お礼日時:2007/03/07 00:21

専門的な知識があると非常に役に立ちます。

先に解答された方は知識が豊富でわかりやすい解説がなされています。
ならば、私は超簡単に書いてみようかと.....

貴方の友達(コンパイラは友達ですよw)に仕事を依頼しましょう。
仕事内容をメモに書いて渡します。友達はそれに従って仕事をします。
しかし、その内容がそのまま仕事として反映されるわけではなく、『多分問題ないだろう』と友達が判断した場合、何かを省いたり、工程を前後させて速度を優先させる可能性があります。
もし、貴方が友達の勝手な判断を嫌い、最適化を許さないならばvolatileを付けてあげます。

まあ、友達から仕返しは無いと思いますが......使う機会が無いか...
    • good
    • 0
この回答へのお礼

sirn様へ
ご回答ありがとうございました。
例え方がわかりやすくて、すんなり理解できました。
ありがとうございました。

お礼日時:2007/03/07 00:25

実は標準ライブラリの中にも、それを使うときはvolatile修飾子を付けることを要求している場合があります。


具体的には、signal関数で登録するシグナル処理ルーチンで操作するsig_atomic_t型の変数であり、setjmpマクロやlongjmp関数を使うときの自動変数です。これらの関数などについて調べてみるとよいでしょう。

# volatile修飾子が気になっているぐらいですから、まったくの初心者ではないと理解しています。
    • good
    • 0
この回答へのお礼

jacta様へ
ご回答ありがとうございました。
ご指摘の関数につきましては、これから一つずつ解決していきたい
と思います。方向付けが出来ましたことを感謝します。
ありがとうございました。

お礼日時:2007/03/07 00:39

参考URLに、最適化される前とされた後のコードが載っています。


非常に単純なコードですので、わかりやすいと思いますよ。


ちなみに、NO3さんの「無駄ループが無くなるのを防ぐ」という目的ですが、volatileをつけても効果がないコンパイラもあると聞いたことがあります。
うろ覚えですが・・・。

基本は、NO3さんの「メモリマップドI/O」とか、NO1さんの並列処理のためではないでしょうか。
PCプログラミングでも、マルチスレッドやソフトウェア割り込みなどで必要になってきますね。

参考URL:http://www.cmagazine.jp/src/kinjite/c/variable.h …
    • good
    • 0
この回答へのお礼

1839cc様へ
ご回答ありがとうございました。
とてもご丁寧に参考URLまで教えていただきまして
感謝しています。ありがとうございました。
>基本は、NO3さんの「メモリマップドI/O」とか、NO1さんの並列処理
なるほど。これからの学習の課題になりそうです。
学習の方向付けが出来ましたことを感謝します。
ありがとうございました。

お礼日時:2007/03/07 01:03

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!