有趣又讨厌的整数问题

Funny and really annoying integer issue

本文关键字:整数 问题 讨厌      更新时间:2023-10-16

所以,我有以下代码,我知道它在某个地方坏了,我根本无法识别在哪里…

static uint64_t get_disk_total(const char* path)
{
    struct statvfs stfs;
    if ( statvfs(path, &stfs) == -1 )
    {
        return 0;
    }
    uint64_t t = stfs.f_blocks * stfs.f_bsize;
    std::cout  << "total for [" << path << "] is:" << t 
               << " block size (stfs.f_bsize):" <<   stfs.f_bsize
               << " block count (stfs.f_blocks):" << stfs.f_blocks 
               << " mul:" << stfs.f_blocks * stfs.f_bsize
               << " hardcoded: " << (uint64_t)(4096 * 4902319)     // line 50
               <<  std::endl ;
    return t;
}

当我编译它时,告诉我:

part_list.cpp: In function ‘uint64_t get_disk_total(const char*)’:
part_list.cpp:50:59: warning: integer overflow in expression [-Woverflow]

好。当我运行它时,结果是(手动添加换行符):

total for [/] is:2900029440 
block size (stfs.f_bsize):4096 
block count (stfs.f_blocks):4902319 
mul:2900029440 
hardcoded: 18446744072314613760

我知道,4902319 * 4096 = 20079898624…谷歌告诉我答案是肯定的。那么在同样的计算中,我究竟是如何先得到2900029440然后得到18446744072314613760的呢?谁能给我解释一下这是怎么回事?这超出了我的综合能力,我觉得,这是一个很小很小的问题隐藏在某个地方…4902319 * 4096不应该是如此大的数字,应用程序不应该像这样疯狂…

谢谢你的帮助!

首先计算(4096 * 4902319),它被计算为int,并且它溢出。然后将该数字转换为uint64_t

试题:

(4096 *  (uint64_t) 4902319) 

将其计算为uint64_t。

使用Unsigned long literal:

   4096 * 4902319ULL
                 ~~~

在计算溢出之前