我尝试了KR练习2.1-通过直接计算确定long变量的范围。

#include <stdio.h>
#include <limits.h>

int main()
{
    unsigned short long_bits =  sizeof( long ) * CHAR_BIT;
    printf( "LONG_MAX   = %ld\n", ( 1L << ( long_bits - 1 ) ) - 1 );
    printf( "LONG_MIN   = %ld\n", ( -1 ) * ( 1L << ( long_bits - 1 ) ) );
    printf( "ULONG_MAX (1) = %lu\n", ( 1UL << long_bits ) - 1 );    // doesn't work

    printf( "ULONG_MAX (2) = %lu\n", 2*( 1UL << ( long_bits - 1 ) ) - 1 );  // work
    printf( "\n" );
}
  • ULONG_MAX (1) = 0是错误的,因为我想是左移溢出。
  • ULONG_MAX (2) = 18446744073709551615似乎正确,方法是将最后一个左移替换为乘以2。

  • 这样看来,左移运算符会遭受溢出,但乘法不会吗?这个中间计算2*( 1UL << ( long_bits - 1 ) )是否比long提升了某种类型?在我的机器中,longlong long完全相同(8字节)。

    编辑:
    正如Lundin所指出的,ULONG_MAX所需的全部是printf( "ULONG_MAX = %lu\n", ~0L );
    在这种情况下使用左移会导致UB,并乘以2也可能是UB(尽管情况2的结果看起来是正确的)。

    最佳答案

    仅当左移量小于类型的大小时,才定义左移值的行为。因此,1UL << long_bits是未定义的行为,任何事情都可能发生,包括恶魔从你的 Nose 中飞出来。

    n为我们正在使用的类型中的位数。实际上,根据平台的不同,在这种情况下会发生两种行为:要么通过n进行任何左移或更多操作都会生成0(随着整个位模式的移出),或者将左移减少为n模,因此按n位置左移的行为类似于按0位置左移的行为,产生1UL << 01

    关于c - 当左移不等于乘以2时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34309613/

    10-09 06:38