Забавная и действительно раздражающая целочисленная проблема

Итак, у меня есть следующий код, я знаю, что он где-то сломан, и я просто не могу определить, где …

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 = 20079898624Google говорит мне, что это так. Так как же я получу в первую очередь 2900029440 а потом 18446744072314613760 для того же расчета? Может кто-нибудь объяснить мне, что здесь происходит? Это выше моих всесторонних возможностей прямо сейчас, и я чувствую, что это крошечная крошечная проблема где-то спрятана … 4902319 * 4096 не должно быть такого огромного числа, чтобы приложение сходило с ума, как это …

Спасибо за помощь!

1

Решение

Сначала вы рассчитываете (4096 * 4902319) который рассчитывается как int и это переполняет.
Затем это число преобразуется в uint64_t,

Пытаться:

(4096 *  (uint64_t) 4902319)

Чтобы сделать это рассчитать как uint64_t.

6

Другие решения

использование Без подписи, долго, долго буквальный:

   4096 * 4902319ULL
~~~

До расчета переполняется.

1

По вопросам рекламы [email protected]