请考虑以下代码:
int i = 3 << 65;
Run Code Online (Sandbox Code Playgroud)
我希望结果是i==0,但实际结果是i==6.通过一些测试,我发现使用以下代码:
int i, s;
int a = i << s;
int b = i << (s & 31);
Run Code Online (Sandbox Code Playgroud)
值a和b始终是相同的.
C标准是否说过关于移位超过32位(类型的宽度int)的任何内容,还是这种未指定的行为?
我在C中有这个代码(仅供学习):
char x;
uint64_t total = 0;
for(x = 20; x < 30; x++){
total = (((((1 << x) * x) / 64) + 1) * sizeof(uint64_t));
printf("%d - %llu\n", x, total);
}
Run Code Online (Sandbox Code Playgroud)
什么是印刷品:
20 - 2621448
21 - 5505032
22 - 11534344
23 - 24117256
24 - 50331656
25 - 104857608
26 - 218103816
27 - 18446744073625665544
28 - 18446744073575333896
29 - 18446744073508225032
Run Code Online (Sandbox Code Playgroud)
为什么在x> 26时我有那些奇怪的值?我在Ubuntu 10.10 64位上的gcc 4.6.1.
我想在我的程序中使用以下代码,但是gcc不允许我将我的1转移到31以上.
sizeof(long int) 显示8,所以这并不意味着我可以离开直到63?
#include <iostream>
using namespace std;
int main(){
long int x;
x=(~0 & ~(1<<63));
cout<<x<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译输出以下警告:
left shift `count >= width` of type [enabled by default] `x=(~0 & ~(1<<63))`;
^
Run Code Online (Sandbox Code Playgroud)
输出为-1.如果我离开31位,我得到2147483647正如预期的那样.
我希望除了MSB之外的所有位都打开,从而显示数据类型可以容纳的最大值.
正如问题标题所示,将2 ^ 31分配给有符号和无符号的32位整数变量会产生意外结果.
这是C++我做的简短程序(in ),看看发生了什么:
#include <cstdio>
using namespace std;
int main()
{
unsigned long long n = 1<<31;
long long n2 = 1<<31; // this works as expected
printf("%llu\n",n);
printf("%lld\n",n2);
printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long) );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
MyPC / # c++ test.cpp -o test
MyPC / # ./test
18446744071562067968 <- Should be 2^31 right?
-2147483648 <- This is correct ( -2^31 because of the sign bit) …Run Code Online (Sandbox Code Playgroud) 请看下面的代码片段,它基本上只是将 1 个字节向左移动 24 位。
uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFF << 24;
printf("after : %016llX \n", i);
// gives:
// before: FFFFFFFF00000000
// after : FFFFFFFEFF000000
Run Code Online (Sandbox Code Playgroud)
最重要的 32 位是FFFFFFFE(E在最后观看)。这并不像我预期的那样。我不明白为什么左移 1 个字节 24 位会触及位 #32(位 #31 应该是最后一个修改的)它把最后一个F( 1111) 变成了E( 1110) 。
为了使其正常工作,我使用了0xFF无符号 ( 0xFFU)。
uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFFU << 24;
printf("after : %016llX \n", i); …Run Code Online (Sandbox Code Playgroud) 对于此函数,计算最多的woodall数 n = 64
并且该算法用于伍德尔为W ñ = N⋅2 Ñ - 1
for (int n = 1; n <= 64; ++n)
{
a[n - 1] = (n * (exp2(n))) - 1;
}
Run Code Online (Sandbox Code Playgroud)
但是在n大于47之后,结果是错误的,因为它似乎忘记- 1了结果n * (exp2(n)).
如果我cout是值via,那么输出是什么
std::cout << i << ":\t" << std::setprecision(32) << a[i - 1] << std::endl;
......之前是正确的
n
45: 1583296743997439
46: 3236962232172543
47: 6614661952700415
48: 13510798882111488
49: 27584547717644288
50: 56294995342131200
Run Code Online (Sandbox Code Playgroud)
......之后是不正确的
for a[]是一个unsigned long int
如果我将- 1 …
即使我投出了每一个正确的操作数unsigned long long,警告仍然存在.不应该uint8_t << uint64_t有这样的隐式演员:(uint64_t) uint8_t << uint64_t?
这个答案表明我可以提升任何一个操作数,并且整个表达式都会被强制转换unsigned long long,但这可能是错误的.
bool dgBioReadU64LE(DgBioFile *file, uint64_t *x) {
uint8_t u[8];
if (!dgBioReadU8v(file, LEN(u), u)) return false;
*x = u[0]|(u[1]<<8ULL)|(u[2]<<16ULL)|(u[3]<<24ULL)|(u[4]<<32ULL)|(u[5]<<40ULL)|(u[6]<<48ULL)|(u[7]<<56ULL);
return true;
}
bool dgBioReadU64BE(DgBioFile *file, uint64_t *x) {
uint8_t u[8];
if (!dgBioReadU8v(file, LEN(u), u)) return false;
*x = u[7]|(u[6]<<8ULL)|(u[5]<<16ULL)|(u[4]<<24ULL)|(u[3]<<32ULL)|(u[2]<<40ULL)|(u[1]<<48ULL)|(u[0]<<56ULL);
return true;
}
Run Code Online (Sandbox Code Playgroud)