bcache源here包含以下行:
schedule_delayed_work(&dc->writeback_rate_update,
dc->writeback_rate_update_seconds * HZ);
writeback_rate_update_seconds
定义为unsigned int
,appears to be 32 bit位于x86_64上,我不确定HZ
的类型,但我相信该值为1000并假设它是32位或更少。
如果我将writeback_rate_update_seconds
设置为2147483647,实际传递给schedule_delayed_work
的值是多少? schedule_delayed_work
的第二个参数似乎是long
,但这并不意味着在乘法溢出之前操作数被提升为很长时间,是吗?
答案 0 :(得分:3)
假设:
#include <stdio.h>
#include <stdlib.h>
int schedule_delayed_work( unsigned long param )
{
printf("value: %lu\n", param);
return 0;
}
int main(int argc, char **argv)
{
unsigned int writeback_rate_update_seconds;
unsigned int HZ;
writeback_rate_update_seconds = 2147483647;
HZ = 1000;
schedule_delayed_work( writeback_rate_update_seconds * HZ );
return 0;
}
您将4294966296
传递给该函数。
如果将函数调用更改为cast:
schedule_delayed_work( (unsigned long) writeback_rate_update_seconds * HZ );
...您将2147483647000
传递给该函数。
我没有看过C标准,看看标准行为是什么,但是测试了这个:
Apple LLVM version 8.1.0 (clang-802.0.38)
Target: x86_64-apple-darwin16.7.0
答案 1 :(得分:2)
如果两个操作数都适合unsigned int
(如果HZ
为常数1000
,则类型为int
并且适合unsigned int
)它们会被提升到unsigned int
。使用unsigned
整数,溢出是明确定义的;结果值是计算的模数(UINT_MAX
加1)。也就是说,最大结果是UINT_MAX
; UINT_MAX + 1
将导致0,UINT_MAX + 2
将导致1,依此类推。
接收者的类型(这里,接收结果的参数的类型)根本不重要。为避免回绕,将其中一个参数转换为更宽的整数类型(例如unsigned long
在64位Linux中为64位;或者甚至更好,使用固定宽度类型,如uint64_t
)。