关于__int64类型使用的一点感受

今天要生成一个20G的单词文件,遇到数据边界的问题,这里记下。

 

要生成这个20G的文件,我首先从一个文件里面读取了一定量的单词,放在缓冲区里面,然后重复把这个缓冲区写入文件。这里我需要计算出循环的次数,如果这么写:

__int64 k = 20;		//20GB的文件需要循环的次数
k = 20 * 1024 * 1024 * 1024 / nStrLen;	//nStrLen:缓冲区字符数

那么恭喜你,结果是0!

因为在计算20*1024*1024*1024的时候,数据是按照32位来对待的,所以实际上当计算结果大于2^32时,就会发生数据截断.请看下面的截图(来自于调试窗口):

image

可见上面的计算结果都是被当做int的。一旦数据结果越界,就会发生数据截断。所谓截断实际上是一个内存块的覆盖,多余的部分被舍弃。当你把一个int赋值给char,多出来的部分就被舍弃。这个截断的结果取决于数据原始的类型,比如上面的int,覆盖以后结果仍然是有符号的。上面的结果可以自己画一下数据在内存里面的存储模型,可以得到跟上面一样的结果。

 

那么如何使上面的计算得到正确的结果呢?答案是让每次计算都不会溢出

把上面的计算乘法改一下就可以实现了:

__int64 k = 20;		//20GB的文件需要循环的次数
k *= 1024 * 1024 * 1024;
k /= nStrLen;
cout << "Loop = " << k << endl;

这里的每次中间运算(1024*1024*1024=2^30 < 2^31-1)都没有超过int的范围

 

这里出现了__int64类型,通过查看msdn可以得知,他是微软编译器对于64整形的拓展,相应的还有unsigned __int64类型。

注意这两种类型的格式化方式:

__int64 i64;

scanf(“%I64d”, &i64);

printf(“%I64d \n”, &i64);

类型

使用的前缀 指定的类型
__int64 I64

d, i, o, x, or X

unsigned __int64 I64

o, u, x, or X

格式化的形式

%[flags] [width] [.precision] [{h | l | ll | I | I32 | I64}]type

在c++中,最好不要使用cout,cin处理__int64,否则结果可能会出现差异,我就遇到输出结果中有字母的情况。相反应该使用c库中的格式化函数处理。

posted @ 2012-03-20 16:27  kcy-666  阅读(4633)  评论(0编辑  收藏  举报