art*_*rtm 5 c bit-manipulation kernighan-and-ritchie
我尝试了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" );
}
Run Code Online (Sandbox Code Playgroud)
ULONG_MAX (1) = 0 是错误的,因为我认为左移溢出.ULONG_MAX (2) = 18446744073709551615 通过用乘以2来替换最后一个左移位似乎是正确的.所以看起来左移运算符会溢出,但乘法不会?这个中间计算是否会2*( 1UL << ( long_bits - 1 ) ) 促进某些类型long?在我的机器上,long并且long long完全相同(8字节).
编辑:正如伦丁指出的那样,所有需要的ULONG_MAX都是printf( "ULONG_MAX = %lu\n", ~0L );
在这种情况下使用左移导致UB,并且乘以2也可能是UB(尽管情况2的结果看起来是正确的).
仅当左移量小于类型的大小时,才定义左移值的行为。因此,1UL << long_bits这是未定义的行为,任何事情都可能发生,包括 d\xc3\xa6mons 从你的鼻子里飞出来。
让n为我们正在使用的类型的位数。n实际上,根据平台的不同,在这种情况下会发生两种行为:要么产生任何左移或更多0(因为整个位模式被移出),要么左移减少模n,因此按位左移的n行为类似于按位左移0,产生1UL << 0或1。
| 归档时间: |
|
| 查看次数: |
184 次 |
| 最近记录: |