'wrapping' 乘法溢出的结果是什么?
What is the result of 'wrapping' a multiplication overflow?
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
,但这并不意味着操作数在乘法溢出之前被提升为 long,对吗?
鉴于:
#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
传递给函数。
如果将函数调用更改为强制转换:
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
如果两个操作数都在 unsigned int
中(如果 HZ
是常量 1000
,它是 int
类型并且在 unsigned int
中)它们'重新晋升为unsigned int
。对于 unsigned
整数,溢出是明确定义的;结果值是计算模值(UINT_MAX
加一)。即最大结果为UINT_MAX
; UINT_MAX + 1
将得到 0,UINT_MAX + 2
将得到 1,依此类推。
接收器的类型(这里是接收结果的参数的类型)根本不重要。为避免环绕,将其中一个参数转换为 更宽的整数类型 (例如 unsigned long
在 64 位 Linux 中是 64 位;或者更好,使用固定宽度的类型,例如 uint64_t
).
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
,但这并不意味着操作数在乘法溢出之前被提升为 long,对吗?
鉴于:
#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
传递给函数。
如果将函数调用更改为强制转换:
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
如果两个操作数都在 unsigned int
中(如果 HZ
是常量 1000
,它是 int
类型并且在 unsigned int
中)它们'重新晋升为unsigned int
。对于 unsigned
整数,溢出是明确定义的;结果值是计算模值(UINT_MAX
加一)。即最大结果为UINT_MAX
; UINT_MAX + 1
将得到 0,UINT_MAX + 2
将得到 1,依此类推。
接收器的类型(这里是接收结果的参数的类型)根本不重要。为避免环绕,将其中一个参数转换为 更宽的整数类型 (例如 unsigned long
在 64 位 Linux 中是 64 位;或者更好,使用固定宽度的类型,例如 uint64_t
).