C++ 奇怪现象合集
DarkBZOJ 4668:手写 swap 与 std::swap
前者:提交记录,TLE,且无法在 DarkBZOJ 上通过题面中的小样例。
后者:提交记录,AC,也无法在 DarkBZOJ 上通过题面中的小样例。
位移运算的数据范围限制
这里以 $32$ 位整数、$64$ 位整数、$128$ 位整数的左移运算为例进行展示。
/*
input:
32
64
128
output:
0
0
1
2
0
0
1
2
0
0
1
2
0
0
1
2
0 0
0 0
0 1
0 2
0 0
0 0
0 1
0 2
*/
#include<cstdio>
int _;
const __int128_t one_128=1;
__int128_t a,b;
const __uint128_t one_u128=1;
__uint128_t c,d;
void print_128(const __int128_t x){
printf("%lld %lld\n",(long long)(x>>64),(long long)x);
}
void print_u128(const __uint128_t x){
printf("%lld %lld\n",(unsigned long long)(x>>64),(unsigned long long)x);
}
int main(){
scanf("%d",&_);
printf("%d\n",1<<32);
printf("%d\n",1<<33);
printf("%d\n",1<<_);
printf("%d\n",1<<(_+1));
printf("%u\n",1u<<32);
printf("%u\n",1u<<33);
printf("%u\n",1u<<_);
printf("%u\n",1u<<(_+1));
scanf("%d",&_);
printf("%lld\n",1ll<<64);
printf("%lld\n",1ll<<65);
printf("%lld\n",1ll<<_);
printf("%lld\n",1ll<<(_+1));
printf("%llu\n",1ull<<64);
printf("%llu\n",1ull<<65);
printf("%llu\n",1ull<<_);
printf("%llu\n",1ull<<(_+1));
scanf("%d",&_);
print_128(one_128<<128);
print_128(one_128<<129);
print_128(one_128<<_);
print_128(one_128<<(_+1));
print_u128(one_u128<<128);
print_u128(one_u128<<129);
print_u128(one_u128<<_);
print_u128(one_u128<<(_+1));
return 0;
}
可以发现,对于位移的移动次数不小于数据类型的位数的情况下,会有两种不同的表现:如果编译器提前知道这次运算的结果,答案就是我们预期的;否则,如果是动态计算的,实际位移次数就是原来的位移次数对数据类型的位数取模后的值。