关于long long 数据类型使用的一个问题
时间:2006-11-06 来源:lanttor.guo
笔记原创: 兰特
联系邮件: [email protected]
系统平台:linux平台,gcc
有这样的一个程序,是关于使用随机函数rand()的:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
time_t tm;
long random_num;
tm = time(NULL);
srand(tm);
while (1) {
random_num = rand()*0x10000 + rand();
if (random_num < 0) {
printf("%0Lx\n", random_num);
break;
}
}
}
这个函数输出一个随机数random_num,运行程序会发现它的输出值是负值;查找程序
很快发现,原来是random_num是一个long类型的变量,rand()*0x10000+rand()的值有
可能大于一个long类型数据的最大尺寸。
让我们分析一下rand()*0x10000+rand()的最大可能值:rand()的最大可能取值为:
RAND_MAX (参考man说明),而 RAND_MAX的值在/usr/include/stdlib.h中定义:
#define RAND_MAX 2147483647,所以我们计算一下rand()*0x10000+rand()最大可能值
为:2147483647*66636+2147483647=143101867785139=0x82267FFEFBB3,这也就意味着
random_num需要至少6个字节的数据类型,那么我们只有选择long long类型了。
因此,上面的代码修改如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
time_t tm;
long long random_num;
tm = time(NULL);
srand(tm);
while (1) {
random_num = rand()*0x10000 + rand();
if (random_num < 0) {
printf("%0Lx\n", random_num);
break;
}
}
}
但是,我们发现random_num输出的依然是负值。经过分析发现,random_num = rand()*0x10000+rand()这条赋值语句中,右值的运算是按照int类型运算的,我们可以查看rand()函数的原型:
int rand(void); 所以当右值的运算超过int类型的最大值,则运算不正确,发生了溢出,所以赋给左值的值肯定是错误的,random_num得出的值为负值就不足奇怪了。
因此上面的代码修改如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
time_t tm;
long long random_num;
tm = time(NULL);
srand(tm);
while (1) {
random_num = (long long)rand()*0x10000 + (long long)rand();
if (random_num < 0) {
printf("%0Lx\n", random_num);
break;
}
}
}
这样,代码就正确了:当然了,正确的代码输出是个死循环,你只能按下ctrl+c终止程序运行。
总结:
这个问题可以看出,long long 类型并不属于int,char,short等内置数据类型一类(因为int,char,short之间
不存在这个问题,它们隐含了数据类型优先级自动转换);在编写代码的同时,我们最好能够
显示的进行数据类型的转换,不依赖于隐含的规则,这样就会少一些BUG。
联系邮件: [email protected]
系统平台:linux平台,gcc
有这样的一个程序,是关于使用随机函数rand()的:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
time_t tm;
long random_num;
tm = time(NULL);
srand(tm);
while (1) {
random_num = rand()*0x10000 + rand();
if (random_num < 0) {
printf("%0Lx\n", random_num);
break;
}
}
}
这个函数输出一个随机数random_num,运行程序会发现它的输出值是负值;查找程序
很快发现,原来是random_num是一个long类型的变量,rand()*0x10000+rand()的值有
可能大于一个long类型数据的最大尺寸。
让我们分析一下rand()*0x10000+rand()的最大可能值:rand()的最大可能取值为:
RAND_MAX (参考man说明),而 RAND_MAX的值在/usr/include/stdlib.h中定义:
#define RAND_MAX 2147483647,所以我们计算一下rand()*0x10000+rand()最大可能值
为:2147483647*66636+2147483647=143101867785139=0x82267FFEFBB3,这也就意味着
random_num需要至少6个字节的数据类型,那么我们只有选择long long类型了。
因此,上面的代码修改如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
time_t tm;
long long random_num;
tm = time(NULL);
srand(tm);
while (1) {
random_num = rand()*0x10000 + rand();
if (random_num < 0) {
printf("%0Lx\n", random_num);
break;
}
}
}
但是,我们发现random_num输出的依然是负值。经过分析发现,random_num = rand()*0x10000+rand()这条赋值语句中,右值的运算是按照int类型运算的,我们可以查看rand()函数的原型:
int rand(void); 所以当右值的运算超过int类型的最大值,则运算不正确,发生了溢出,所以赋给左值的值肯定是错误的,random_num得出的值为负值就不足奇怪了。
因此上面的代码修改如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
time_t tm;
long long random_num;
tm = time(NULL);
srand(tm);
while (1) {
random_num = (long long)rand()*0x10000 + (long long)rand();
if (random_num < 0) {
printf("%0Lx\n", random_num);
break;
}
}
}
这样,代码就正确了:当然了,正确的代码输出是个死循环,你只能按下ctrl+c终止程序运行。
总结:
这个问题可以看出,long long 类型并不属于int,char,short等内置数据类型一类(因为int,char,short之间
不存在这个问题,它们隐含了数据类型优先级自动转换);在编写代码的同时,我们最好能够
显示的进行数据类型的转换,不依赖于隐含的规则,这样就会少一些BUG。
相关阅读 更多 +