6

私はこのc++コードを使用して、Windows内のいくつかのファイルのファイルサイズを検索しました(Visual Studioを使用)。

(p_findFileData->nFileSizeHigh * MAXDWORD) + p_findFileData->nFileSizeLow);

ファイルが4GBより大きい場合、これでは正しいファイルサイズが得られませんでした。いくつかの調査の後、私は試しました:

(p_findFileData->nFileSizeHigh * (MAXDWORD+1)) + p_findFileData->nFileSizeLow); 

nfilesizehighとnfilesizelowはそれぞれファイルサイズの64ビット値の32ビットであり、ファイルサイズ値が32ビットより大きい場合は、maxdword(私の場合は0xffffffff)にnfilesizehighを掛けます。2番目の解決策も機能せず、サイズが以前よりも小さくなりました。私は再びこれを試しました:

ULONGLONG FileSize = (FindFileData.nFileSizeHigh * 4294967296) + FindFileData.nFileSizeLow;

そしてそれはうまくいった。また、別のソリューションを使用して、これと一緒にファイルサイズも取得しました。

 ULONGLONG FileSize = FindFileData.nFileSizeHigh;
 FileSize <<= sizeof( FindFileData.nFileSizeHigh ) *8; 
 FileSize |= FindFileData.nFileSizeLow;

上記の解決策も機能します:

コードの内部動作を知りたいので、最初の2つのソリューションが機能しなかった理由と、可能であれば最後のソリューションの説明も知りたいと思いました。助けていただければ幸いです。

4

4 に答える 4

10

ULARGE_INTEGER手動で値を計算/シフトするのではなく、構造体を使用して値を結合します。

ULARGE_INTEGER ul;
ul.HighPart = p_findFileData->nFileSizeHigh;
ul.LowPart = p_findFileData->nFileSizeLow;
ULONGLONG FileSize = ul.QuadPart;
于 2013-03-04T20:41:00.690 に答える
8

私は使うだろう :

ULONGLONG FileSize = (static_cast<ULONGLONG>(FindFileData.nFileSizeHigh) <<
                      sizeof(FindFileData.nFileSizeLow) *8) |
                     FindFileData.nFileSizeLow;

ULONGLONGへのキャストは、FileSize変数に入る前に32ビット値を64ビット値にするために必要です。

もちろん、乗算も使用できますが、特定の方法で「より良い」わけではなく、おそらく少し遅くなります[この特定のケースではおそらく大したことではありませんが、乗算を使用してもメリットはありません。 。

そして今、「機能していない」バリアントの場合:

これが機能する場合でも:

 (p_findFileData->nFileSizeHigh * MAXDWORD) + p_findFileData->nFileSizeLow);

は4GBよりも小さいため、間違った値を取得することになります。そのため、間違った値になっMAXDWORDてしまいます[はい、おそらく近いですが、少なくとも1バイト間違っている可能性があります]。ただし、32ビット値を扱っているため、実際には次のようになります。

 -p_findFileData->nFileSizeHigh + p_findFileData->nFileSizeLow;

MAXDWORDは-1と同じであるため(はい、符号なしの値である可能性がありますが、そのように値をオーバーフローさせると、負の符号付きの値とまったく同じように動作します)。

これは数学的には正しいですが、32ビット値をオーバーフローするため機能しません。

 (p_findFileData->nFileSizeHigh * (MAXDWORD+1)) + p_findFileData->nFileSizeLow);

だからあなたlow part + (0 * high part)はもちろん間違っているものを手に入れます。

キャストを使用すると、これは機能します:

 static_cast<ULONGLONG>(p_findFileData->nFileSizeHigh) * (MAXDWORD+1) +
 p_findFileData->nFileSizeLow;
于 2013-03-04T19:23:23.723 に答える
3
(p_findFileData->nFileSizeHigh * MAXDWORD) + p_findFileData->nFileSizeLow);

MAXDWORDの値が間違っているため、これでは正しい結果が得られません。

(p_findFileData->nFileSizeHigh * (MAXDWORD+1)) + p_findFileData->nFileSizeLow); 

値を保持するのに十分な大きさに型をキャストする前にMAXDWORDに+1を追加しているため、これは機能しません。

(FindFileData.nFileSizeHigh * 4294967296) + FindFileData.nFileSizeLow;

これ4294967296は64ビットタイプであるため機能します。

FileSize <<= sizeof( FindFileData.nFileSizeHigh ) *8; 
FileSize |= FindFileData.nFileSizeLow;

これは、上位ビットを32シフトし(4294967296を乗算するのと同じです)、ビット単位またはを使用して下位ビットを「追加」するために機能します。

于 2013-03-04T19:21:14.847 に答える
1

私はまったく同じ問題を抱えていましたが、私のコードの答えは本当に簡単でした。MAXDWORDを64ビットint(uint64_tなど)にキャストするだけです。この背後にある説明は、私がここで受け取った回答にあります。

于 2018-11-06T09:27:43.197 に答える