基本上当我这样做时,32位系统会发生什么:
uint32_t test (void) { uint32_t myInt; myInt = ((0xFFFFFFFF * 0xFFFFFFFF) % 256u ); return myInt; }
我们假设int是32位.
> 0xFFFFFFFF将具有unsigned int类型.有一些特殊的规则可以解释这一点,但因为它是一个十六进制常量并且它不适合int,但它适合unsigned int,它最终会成为unsigned int.
> 0xFFFFFFFF * 0xFFFFFFFF将首先进行通常的算术转换,但由于双方都是无符号整数,因此没有任何反应.乘法的结果是0xfffffffe00000001,它通过使用模232值减少为无符号整数,从而得到类型为unsigned int的值1.
>(unsigned int)1%256u等于1且类型为unsigned int.通常的算术转换也适用于此,但同样,两个操作数都是无符号整数,因此没有任何反应.
>结果转换为uint32_t,但它已经是unsigned int,具有相同的范围.
但是,让我们假设int是64位.
> 0xFFFFFFFF将具有int类型.
> 0xFFFFFFFF * 0xFFFFFFFF会溢出!这是未定义的行为.在这一点上,我们不再试图弄清楚程序的作用,因为它可以做任何事情.也许编译器决定不为这个函数发出代码,或者同样荒谬的东西.
这将发生在所谓的“ILP64”或“SILP64”架构中.这些架构很少见,但确实存在.我们可以通过使用0xFFFFFFFFu来避免这些可移植性问题.