質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

2707閲覧

C言語 volatile宣言について

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/08/01 05:13

編集2016/08/31 07:06

###前提・実現したいこと
Visual studio 2015のコミュニティ版で練習問題のプログラムを作っています。
volatile宣言を使用した場合と使用しない場合の違いをアセンブラコードで確認する
といった内容なのですが、違いが無いように見えます。
使用した場合は3回分データの取り出しを行う物のようですが、使用の前後で変わらない為、
使用後が3回データの取り出しを行えていないのか、
それともそもそも使用前の時点で最適化されずに3回データを取り出しているのか、
どちらなのでしょうか。出来ればその原因が分かればいいのですが…

###発生している問題・エラーメッセージ
使用前

#include "stdafx.h" #include <stdlib.h> int vdata = 0; int dt1, dt2, dt3; int main(void) { 01281690 push ebp 01281691 mov ebp,esp 01281693 sub esp,0C0h 01281699 push ebx 0128169A push esi 0128169B push edi 0128169C lea edi,[ebp-0C0h] 012816A2 mov ecx,30h 012816A7 mov eax,0CCCCCCCCh 012816AC rep stos dword ptr es:[edi] dt1 = vdata; 012816AE mov eax,dword ptr [vdata (01289138h)] 012816B3 mov dword ptr [dt1 (01289594h)],eax dt2 = vdata; 012816B8 mov eax,dword ptr [vdata (01289138h)] 012816BD mov dword ptr [dt2 (01289590h)],eax dt3 = vdata; 012816C2 mov eax,dword ptr [vdata (01289138h)] 012816C7 mov dword ptr [dt3 (01289580h)],eax system("pause"); 012816CC mov esi,esp 012816CE push offset string "pause" (01286B30h) 012816D3 call dword ptr [__imp__system (0128A160h)] 012816D9 add esp,4 012816DC cmp esi,esp 012816DE call __RTC_CheckEsp (0128110Eh) return 0; 012816E3 xor eax,eax } 012816E5 pop edi 012816E6 pop esi 012816E7 pop ebx 012816E8 add esp,0C0h 012816EE cmp ebp,esp 012816F0 call __RTC_CheckEsp (0128110Eh) 012816F5 mov esp,ebp 012816F7 pop ebp 012816F8 ret

使用後

#include "stdafx.h" #include <stdlib.h> volatile int vdata = 0; int dt1, dt2, dt3; int main(void) { 010E1690 push ebp 010E1691 mov ebp,esp 010E1693 sub esp,0C0h 010E1699 push ebx 010E169A push esi 010E169B push edi 010E169C lea edi,[ebp-0C0h] 010E16A2 mov ecx,30h 010E16A7 mov eax,0CCCCCCCCh 010E16AC rep stos dword ptr es:[edi] dt1 = vdata; 010E16AE mov eax,dword ptr [vdata (010E9138h)] 010E16B3 mov dword ptr [dt1 (010E9594h)],eax dt2 = vdata; 010E16B8 mov eax,dword ptr [vdata (010E9138h)] 010E16BD mov dword ptr [dt2 (010E9590h)],eax dt3 = vdata; 010E16C2 mov eax,dword ptr [vdata (010E9138h)] 010E16C7 mov dword ptr [dt3 (010E9580h)],eax system("pause"); 010E16CC mov esi,esp 010E16CE push offset string "pause" (010E6B30h) 010E16D3 call dword ptr [__imp__system (010EA160h)] 010E16D9 add esp,4 010E16DC cmp esi,esp 010E16DE call __RTC_CheckEsp (010E110Eh) return 0; 010E16E3 xor eax,eax } 010E16E5 pop edi 010E16E6 pop esi 010E16E7 pop ebx 010E16E8 add esp,0C0h 010E16EE cmp ebp,esp 010E16F0 call __RTC_CheckEsp (010E110Eh) 010E16F5 mov esp,ebp 010E16F7 pop ebp 010E16F8 ret

###該当のソースコード
使用前

#include "stdafx.h" #include <stdlib.h> int vdata = 0; int dt1, dt2, dt3; int main(void) { dt1 = vdata; dt2 = vdata; dt3 = vdata; system("pause"); return 0; }

使用後

#include "stdafx.h" #include <stdlib.h> volatile int vdata = 0; int dt1, dt2, dt3; int main(void) { dt1 = vdata; dt2 = vdata; dt3 = vdata; system("pause"); return 0; }

###試したこと
記述ミスの確認

###補足情報(言語/FW/ツール等のバージョンなど)
環境
Windows 7 Professional
ツール
Microsoft Visual Studio Community 2015
Version 14.0.25420.01 Update3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

おそらく、デバッグモードでコンパイルしているから違いが出ないのではないかと思います。

デバッグモードでは、デバッグの都合上、「C言語での行」と対応付けをするように機械語を生成しますので、行を超えるような最適化は基本的に行われません。

一方で、リリースビルドにすると、dt1dt2dt3への代入は「同じ」vdataの値を代入するので、一度読み取ってレジスタに置いておいて、2回め以降はそれを使い回す、という最適化が可能となります。volatileありの時はそうもいかないので、vdataの読み取りをソースコード上と同じく、3回行います。

投稿2016/08/01 05:23

編集2016/08/01 05:29
maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/01 06:00

ありがとうございます。 リリースビルドにしたら問題ありませんでした。 普段からデバッグモードでコンパイルする為、そのような違いがあるとは知りませんでした。とても勉強になりました。
guest

0

これならどうですか?

c

1volatile int vdata = 0; 2int dt1 = 1, dt2 = 2, dt3 = 3; 3 4int main(void) 5{ 6 vdata = dt1; 7 vdata = dt2; 8 vdata = dt3; 9 10 system("pause"); 11 12 return 0; 13}

投稿2016/08/01 05:18

ttyp03

総合スコア16996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/01 07:55

結果は変わらずでした…。 でもmaisumakunさんの方法を試したら上手くいきました。 コメントありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問