6

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

 3 years ago
source link: https://blog.popkx.com/c-programming-multiply-does-not-match-expect/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

发表于 2018-06-19 11:06:34   |   已被 访问: 585 次   |   分类于:   Linux笔记   |   暂无评论

今天用 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笔记


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK