c语言编程,两数相乘,结果总是不对,不符合预期

今天用 C 语言编程时,发现一个非常奇怪的现象:逻辑一切正常,输出却不对。采用 GDB 调试(可参考:gdb工具的使用),定位到错误,居然是乘法运算出了问题。两个数字相乘,结果却是不正确的,始终是错误的

问题发现


发现出问题的代码出现在:

usedSize = 0;
usedSize += pmInfo->videoSize*pmInfo->videoCnt;
usedSize += pmInfo->picSize*pmInfo->picCnt;
usedSize += pmInfo->logSize*pmInfo->logCnt;
usedSize += pmInfo->logIndexSize*pmInfo->logIndexCnt;
usedSize += pmInfo->videoIndexSize*pmInfo->videoIndexCnt;
usedSize += pmInfo->picIndexSize* pmInfo->picIndexCnt;

使用 GDB 定位到此的:

从上图可以看出, pmInfo->videoSize = 268435456,pmInfo->videoCnt= 146,二者相乘的结果应该是:

146 * 268435456 = 39191576576

但是,程序输出的结果却是 536870912,这很奇怪。

现象分析


其实发生这种现象的原因真的非常白痴,就是 数据溢出 了。以我的机器为例,在 c 语言的计算过程中,所有乘数默认都是 int 型的,268435456 显然超出了 int 型能够表示的最大数据,计算当然出错了。

这种现象在编译时,其实就能避免,一般出现这种情况时,编译器会出现 warnning 警告的。以下是一个简单的测试 demo:

#include <stdio.h>

void main()
{
    unsigned long long i = 0;

    i = 146*0xffffff;

    printf("i: %lld\n", i);
}

执行编译:

$ gcc -o test test.c
test.c: In function ‘main’:
test.c:7:12: warning: integer overflow in expression [-Woverflow]
     i = 146*0xffffff;
            ^
$ ./test
i: -1845493906

很明显,编译器已经提示我们 overflow 了。

开发时,我习惯先忽略 warnning,最后再一起解决。这不是一个好习惯,我们也不该忽略它。

解决问题


知道原因,解决起来其实很简单,加上强制转换符就可以了,如下:

#include <stdio.h>

void main()
{
    unsigned long long i = 0;

    i = 146*(unsigned long long)0xffffff;

    printf("i: %lld\n", i);
}

再编译执行,发现问题已经解决了。

$ gcc -o test test.c
$ ./test
i: 2449473390
阅读更多:   Linux笔记
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif