2 ^ n - 1没有溢出长

时间:2016-10-02 07:04:58

标签: c undefined standards integer-overflow c89

这是针对C89项目的,其中LONG_IS_64BIT被定义,如果(且仅当)long是64位,即包含来自-2 ^ 63-1的所有整数到2 ^ 63-1。否则(通过C标准)它包含从-2 ^ 31-1到2 ^ 31-1的所有整数。

我有一个n,如果定义LONG_IS_64BIT,则保证为0到63(含),否则为0到31(含)。我想计算2 ^ n-1,它适合在长的内部。

目前代码有(1L<<n) - 1,但在极有可能的情况下long s正好是32位或64位,这是未定义的行为。 (在程序n==63的这一部分几乎是不可能的,但在32位计算机上n==31肯定会发生。)什么是正确的方法?

我想我可以测试一下n==31n==63,但感觉很糟糕。

1 个答案:

答案 0 :(得分:2)

如果您知道long的数学值适合n == 0 ? 1 : ((1L<<n-1)-1<<1)+1 ,则可以通过计算减去1的值,然后加1,而不是计算值来确保不会溢出加一,然后减一。

n == 0

它是错综复杂的,如果#ifdef LONG_IS_64BIT 0x7FFFFFFFFFFFFFFF>>(63-n) #else 0x7FFFFFFF>>(31-n) #endif 需要特殊的套管以避免左移一个负值,但至少它会为你提供所需的价值。

或者,您可以使用右移:

LONG_MAX

如果它可能比您预期的要大,那么您无法使用unsigned long

但实际上,@ melpomene使用long的评论应该足够好了。在编写标准时,与long具有相同数值位的平台已经不常见了。如果您已经假定<html> <head> <script type="text/JavaScript"> function unload(){ alert("My Page unLoad - Destroy Variable"); } function load() { alert("My Page Load"); } </script> </head> <body onLoad="load()"> <script type="text/javascript"> window.onbeforeunload = unload(); </script> </body> </html> 将具有正好32位或正好64位,那么您可能不应该担心更深奥的实现。