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

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

ただいまの
回答率

87.49%

C言語 volatile宣言について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,996
退会済みユーザー

退会済みユーザー

前提・実現したいこと

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/01 15:00

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

    キャンセル

+1

これならどうですか?

volatile int vdata = 0; 
int dt1 = 1, dt2 = 2, dt3 = 3;

int main(void) 
{ 
    vdata = dt1; 
    vdata = dt2; 
    vdata = dt3;

    system("pause");

    return 0; 
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/01 16:55

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

    キャンセル

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

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る