C++ 奇怪现象合集

DarkBZOJ 4668:手写 swapstd::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;
}

可以发现,对于位移的移动次数不小于数据类型的位数的情况下,会有两种不同的表现:如果编译器提前知道这次运算的结果,答案就是我们预期的;否则,如果是动态计算的,实际位移次数就是原来的位移次数对数据类型的位数取模后的值