我可以在临时结果中溢出uint32_t吗?

时间:2018-02-02 20:07:05

标签: c

基本上当我这样做时,32位系统会发生什么:

uint32_t test (void)
{
  uint32_t myInt;

  myInt = ((0xFFFFFFFF * 0xFFFFFFFF) % 256u );

  return myInt;
}

2 个答案:

答案 0 :(得分:11)

我们假设int是32位。

  1. 0xFFFFFFFF的类型为unsigned int。有一些特殊的规则可以解释这一点,但因为它是一个十六进制常量并且它不适合int,但它适合unsigned int,它最终为unsigned int

  2. 0xFFFFFFFF * 0xFFFFFFFF将首先进行通常的算术转换,但由于双方都是unsigned int,所以没有任何反应。乘法的结果是0xfffffffe00000001,通过使用模2 32 值减少到unsigned int,得到值为unsigned int的值。

  3. (unsigned int)1 % 256u等于1且类型为unsigned int。通常的算术转换也适用于此,但同样,两个操作数都是unsigned int,所以没有任何反应。

  4. 结果转换为uint32_t,但它已经unsigned int具有相同的范围。

  5. 然而,让我们假设int是64位。

    1. 0xFFFFFFFF的类型为int

    2. 0xFFFFFFFF * 0xFFFFFFFF会溢出!这是未定义的行为。在这一点上,我们不再试图弄清楚程序的作用,因为它可以做任何事情。也许编译器决定不为这个函数发出代码,或者同样荒谬的东西。

    3. 这将发生在所谓的" ILP64"或" SILP64"建筑。这些架构很少见,但它们确实存在。我们可以使用0xFFFFFFFFu来避免这些可移植性问题。

答案 1 :(得分:0)

无符号整数溢出意味着您可以尝试将一个值设置为大于它可以容纳的范围 - 但它将换行并将一个模数UINT32_MAX+1。事实上,在这种情况下,如果您使用整数文字附加Uu,也会发生。否则整数文字被认为是,当结果是签名时(因为你没有指定任何东西),将导致由于乘法和有符号整数溢出而导致溢出,这是未定义的行为。

再次回到解释,这里当你将它相乘时(确保它们是无符号的(结果)将通过包裹在UINT32_MAX+1中包裹它意味着如果它大于{{1}然后结果将应用于uint32_t模数,然后我们使用UINT32_MAX进行模运算,然后将结果存储在256u中并从方法返回。 (注意,如果溢出的乘法结果将首先作为uint32_t的模数)