忙しい現代人の腰&肩のお悩み対策!

私はプログラムの初心者です。

Windowsの正確な時刻をミリ秒レベルで取得するために”GetLocalTime”で取得しようと考えていたのですが、マイクロソフトのmsdnに

システムが時刻を生成するのは毎秒 18 回です。したがって、Interval プロパティはミリ秒単位で設定されますが、間隔の真の精度は最大で 18 分の 1 秒です。

との記述があります。
上記であれば、約55.5ミリ秒毎にシステムの時刻を作成しているので、OSはどのようにして”GetLocalTime”で取得できるミリ秒の時間を作成しているのでしょうか。

実際に”GetLocalTime”で取得できるミリ秒での時刻の精度はどれ位なのでしょうか。
”GetLocalTime”以外にOSの正確な時刻を取得する方法はあるのでしょうか。

宜しくお願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (4件)

私の記憶が確かなら、NT、2000、XPにおいてはCPUの種類、OS(Serverか否か)によってチックカウントがインクリメントされるタイミングが違うはず(10か15msec)です。


これらのOSでは一定タイミングごとにタイマー割り込みが発生しその際にOSが保持するチックカウントをインクリメントします。
GetTickCount()はこのチックカウントに先ほどのインクリメントタイミングを乗じたものが返されます。
GetLocalTime()はこれにOS起動時の時間を足したものが返されたと記憶しています。

リアルタイムOSではないので、いずれの関数を使用しても正確な時間を完全には取得することはできません。
確かに一定間隔で時間補正は行っていますが、そのずれが10msec以内になるようには補正してくれるわけではないです。かなりアバウトだったと思います。
この意味ではNTPで標準時刻と合っているOS時刻に合わせることは可能でしょうが、
NTPで標準時刻と合っているOS時刻自体が厳密な意味では正確ではないです。
    • good
    • 0

55.5msec単位に処理している以上、基本的には単純に55.5msecを加算していると思います。


これで数値的には.1msecの単位まで値はでますね。
もちろん、精度は55.5msecですが。

通常のWindowsで最も精度が高い時間計測の方法は
QueryPerformanceCounter,QueryPerformanceFrequency
を使うことです。(使えない場合がある)
但し、時刻ではありません。
OS自体、msec単位の高精度の時刻は提供していないでしょう。

また、Windowsは通常スレッドスイッチが10msec単位ですし、OSがリアルタイムOSでもありませんし、
高い精度での時間処理は非常に困難です。
初心者と自称される方には無理だろうと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
msec単位の高精度の時刻は提供していないとのことで、時間計測等を駆使して頑張ってみたいと考えます。

お礼日時:2005/06/03 11:59

完全な計時方法はありません。

通常はGetLocalTimeを使用しますが、Win95で13mSec, Win98で5mSec, NTで10mSec程度の誤差が出ます。しかし、通常の用途ではこれで十分です。これ以上の精度が必要な場合、timeGetTimeやGetTickCountを使用する必要があります。それでも完全にはなりません。ラウンドロビン優先順位以上のリアルタイム優先順位にするとかドライバを作るとかすればもう少しましになると思いますが、OSは時計ではありません。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
ちなみに、今回作成しようとしていた内容は、自作のソフトに独自の時刻(標準時刻と一定時間ずらす目的)を持たせ、NTPで標準時刻と合っているOS時刻との時刻差を定周期に比較することで、自作ソフトの時刻の精度(10ms以内の誤差)を上げようと考えておりました。

お礼日時:2005/06/01 18:57

GetLocalTimeでの返却値は、


Windows98の時代は、毎秒18回でインクリメントされるカウンタを55.5倍して、OSを立ち上げた時刻を足して返していると思います。
WindowsXPはどうなっているか分かりません。
    • good
    • 0
この回答へのお礼

早急な回答ありがとうございました。
ちなみに今回対象としているOSはWindows2000ですが、このOSの場合はどうなるのでしょうか。

お礼日時:2005/06/01 18:24

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

QDWORDの実際の型は何でしょうか

VC++.NETの環境です。
DOWRD dw1 = 1;
int i = 2; と定義し
ここで
if ( i > dw1 ){
何かの処理;
}
とコーディングすると
warning C4018: '>' : signed と unsigned の数値を比較しようとしました。
のワーニングがでます。
これは、DWORDがint型でなくunsigned int型のようにも見えます。
ある本によれば(VC++.V.NET逆引き大全500の極意)
DWORD はint型であると記述されています。
もし、int型ならこのワーニングはでないはずなのですが、
なぜでるのでしょうか。又、DWORDの実際の型は何なのでしょうか。ご存じのかたおりましたら、教えていただけませんでしょうか。

Aベストアンサー

型定義が知りたいのならば、宣言ファイルを見れば疑問を挟む余地もありません。
DWORD型はwindef.hで
"typedef unsigned long DWORD;"
と宣言されています。

Visual Studioを使っているのならば、知りたい型の上にマウスポインタを置いて右クリック、ポップアップメニューの「定義へ移動」または「宣言へ移動」で簡単に知ることが出来ます。

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

QC ファイル出力で、フォルダがない場合でも作成する方法

先日、皆さんに教えていただき

Cで出力ファイルを指定のフォルダに出す方法が上手く出来ました。
具体的には、↓こうやって指定しました。
sprintf( buff, "%s\\%s", path, filename );

やっていて思ったのですが、
この方法だと、指定フォルダが最初から無いとエラーが出てしまいます。
フォルダが無かったら、作成し、その中にファイルを出力していってくれる。という方法はできるものなのでしょうか?

もしできるようなら教えて下さい!!
よろしくお願いします!

Aベストアンサー

★回答ではないが余談。
・koko_u_ さんありがとう。
 気づくとアンダーバーの関数名で置き換わっているみたいですね。
 他にも気づくといろいろ置き換わっていますね。
 C 関数、最近使っていないのでアンダーバーの関数名で調べてみます。
・ありがとうございました。

●質問者さんへ。
・_mkdir() 関数が使える場合はその関数でもフォルダ(ディレクトリ)が作成できます。
 それでは。

参考URL:http://www5c.biglobe.ne.jp/~ecb/c/12_14.html

Q初級者の質問――time_tについて

私はC言語の初級者です。

time関数というのは現在時刻をtime_t型で返すものですよね。
でも、私はこの意味がよくわかりません。

time_t型とは何でしょうか。

単なる整数なのでしょうか。
確か、time_t型というのは整数で、
1970年1月1日0時からの秒数(世界標準時)だと聞いた気がします。

しかし、(いくつか見てみましたが)大抵のC言語の本では、そういう説明はしていません。
「プログラミング言語C」(カーニハン、リッチー)という本では、
「timeは現在のカレンダー時間を返す。」
と説明しています。
「じゃあ、カレンダー時間って何?」と思いますが、「カレンダー時間」というものの説明は見当たりません。

time_tというのは整数と考えてよいのでしょうか。
time_tで変数宣言すると、プログラムを読む人が「あ、これは時間を表すんだな」とわかり易いから、time_tというものがあるのでしょうか。

それとも、
time_tが秒数を表すかどうかは処理系に依存するのでしょうか。

もし、1970年1月1日からの秒数を表すなら、time関数の戻り値を1年間の秒数で割って1970に足せば今何年かわかるプログラムになりそうですよね。(うるう年や時差は考慮する)
それとも、それは処理系によっては正しく動かないプログラムになるのでしょうか。
(あくまでも考え方です。確か、time_tを渡せば年月日時分秒を返す関数があると思います。)



ちなみに、おとといプログラムを作ってtime関数の戻り値を10進数で表示すると次のようになりました。(VC++)


==============プログラム==============

#include <stdio.h>
#include <time.h>

int main(void)
{
time_t a;
a=time(NULL);
printf("%d\n",a);

return(0);
}

================結果===============

1005300371

私はC言語の初級者です。

time関数というのは現在時刻をtime_t型で返すものですよね。
でも、私はこの意味がよくわかりません。

time_t型とは何でしょうか。

単なる整数なのでしょうか。
確か、time_t型というのは整数で、
1970年1月1日0時からの秒数(世界標準時)だと聞いた気がします。

しかし、(いくつか見てみましたが)大抵のC言語の本では、そういう説明はしていません。
「プログラミング言語C」(カーニハン、リッチー)という本では、
「timeは現在のカレンダー時間を返す。」
と...続きを読む

Aベストアンサー

> C99とは、ISOの規格で比較的新しいものと思います。

そうです。
正式にはISO/IEC 9899:1999です。

> (C98というのは知りませんでした。)
失礼しました。
C89の間違いです。
同様にISO/IEC 9899:1989です。

> しかし、時間の起点が2000年1月1日であっても、秒数でなくて日数であっても、かまわないのでしょうか
時間の起点(というか、時間の管理方法)は time()の管轄であり、型であるtime_tは「time()が返す値を表現できること」が要求されているに過ぎません。
また、「1970年1月1日0時0分0秒からの経過秒数」というのは慣例に過ぎません。

とはいえ、UNIXを起源とする『time_tはlong』と『time()は1970年1月1日0時0分0秒からの経過秒数』という約束事は変えられる事は無いでしょう。
C98/C89との互換性を保ちながら新規格を作ることが予想されるからです(そうでなければlong longなどという型は作らないはず)。
その意味でyoushirさんのおっしゃるとおりだと思います。

> C99とは、ISOの規格で比較的新しいものと思います。

そうです。
正式にはISO/IEC 9899:1999です。

> (C98というのは知りませんでした。)
失礼しました。
C89の間違いです。
同様にISO/IEC 9899:1989です。

> しかし、時間の起点が2000年1月1日であっても、秒数でなくて日数であっても、かまわないのでしょうか
時間の起点(というか、時間の管理方法)は time()の管轄であり、型であるtime_tは「time()が返す値を表現できること」が要求されているに過ぎません。
また、「1970年1月1日0...続きを読む

Qunsigned long long 型のフォーマット指定子

unsigned long long 型の変数の値を表示したいのですが、
フォーマット指定子は%ldですか?
よろしくおねがいします。

Aベストアンサー

規格上は、%llu のように ll を付けます。(unsigned long longなので、%lld ではなく %llu です。)
ただし、C99に準拠した処理系ではなく、単に独自拡張としてlong long型をサポートしている場合には、%Lu とか %qu とかになる場合もあります。場合によっては、long long型が存在する処理系でも、printf系関数で正しく書式化する方法が存在しないこともあり得ます。

Q構造体の初期化のmemsetの第三引数

memset(&lvitem, 0, sizeof(LVITEM));
memset(&lvitem, 0, sizeof(lvitem));
LVITEMに特化した質問ではなく構造体の初期化について、この2つの書き方によるソース管理やコンパイルでのメリットとデメリットを教えてください。

Aベストアンサー

(1)memset(&lvitem, 0, sizeof(LVITEM));
この書き方は、構造体LVITEMを初期化しているんだな、と分かりやすい。
(2)memset(&lvitem, 0, sizeof(lvitem));
この書き方はとにかく変数lvitemを初期化するんだな、という感じだが、型が分からないので宣言しているところを参照しなければならない。
それともう一つ、ただ単に何回も初期化するんでなければ、こういう書き方もできる。
(3)LVITEM lvitem = {0};

結局どれがいいのかといえば、個人的にはケースバイケースですねえ。初期化を1回すればいいような感じなら(3)、構造体名を明示した方が調べる手間がなくなるようなら(1)、そうでなければ(2)を使います。
コンパイルでのメリット、デメリットは特にないんじゃないかなあ。アセンブラがまだ全盛だった頃ならともかく、いまじゃどのコンパイラだって最適化オプションで同じようなコードはくでしょう。
気にするほどでもないと思うけど…

QLPCWSTRとchar

質問なのです・・・

現在、私は[Visual Stdio.Net 2005]を使って、C++のプログラミングをしようと思いまして、今日参考書を見てやってみたのですが、

charの配列を使って、文字列を格納しそれを使おうとしたら、LPCWSTRのキャストが必要というエラーがでました。
参考書だと普通に通るらしいのですが・・・Visual Stdio.Net 2003と2005の違いなのでしょか?わかる方教えていただけませんでしょうか??

Aベストアンサー

補足です。
2005デフォルトのUNICODEを変更する方法は
プロジェクト->プロパティ->構成プロパティ->全般 の中にある
文字セットを[Unicode 文字セットを使用する]から[マルチバイト文字セットを使用する]
に変更することで可能です。

Qファイル名である文字列からbasenameを取得したい

ファイル名である文字列からbasenameを(スマートに)取得したいです。
Perlでは何も考えなくてもできたのですが、C(もしくはC++)では次のようなやりかたしか思いつきません。
これでできているので問題ないのですが、何だかモヤモヤします。
また、このやり方では拡張子はピリオド含めて4文字であること前提なのもモヤモヤの原因です。
Perlのようにもっとスマートなやりかたはないでしょうか?

---------------------------------
char filename[] = "test.dat";
char basename[128];

strncpy(basename, filename, strlen(filename)-4);
basename[strlen(filename)-4] = '\0';
---------------------------------

Aベストアンサー

拡張子がないとか、base自体に.を含むとか、考えると、例えばVCなら_splitpath関数を使うのが一番スマートかも。

C++ならstd::string::find_last_ofで.を探して、
std::string::substrやiterator等の組み合わせで部分文字列を抽出するとか。

Q数値を std::string に変換

C++で 数値を std::string に変換 する方法はあるのでしょうか?
<< や += などやってみましたができませんでした。
やはりC同様に snprintf() などを使うしかないのでしょうか?

Aベストアンサー

#include <sstream>
#include <string>

int n = -1234;
std::ostringstream stream;
stream << n;
std::string result = stream.str();


人気Q&Aランキング