如果我对左移运算符和小端的理解是正确的,那么下面x
的值应该在小端机器上0
。
uint64_t x = ((uint64_t)1<<63);
内存中的(uint64_t)1
看起来像0x0100000000000000
,左移 63 会将其更改为0x0000000000000000
这是0
。所以x
应该是0
. 但是当我在我的 x86-64 机器上运行以下内容时
int main()
{
uint64_t x = ((uint64_t)1)<<63;
printf("%lun", x);
}
我得到的输出是9223372036854775808
. 我在这里做错了什么?
(uint64_t)1
的值为0x0000000000000001
。此值在内存上的表示方式不应影响计算。
将此值向左移动 63 得到0x8000000000000000
,这是十进制9223372036854775808
。
你做错的是格式说明符。您应该使用PRIu64
(在inttypes.h
中定义)来打印uint64_t
。%lu
用于unsigned long
,传递具有错误类型的数据会调用未定义的行为。
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
uint64_t x = ((uint64_t)1)<<63;
printf("%" PRIu64 "n", x);
}
移位运算符不依赖于小或大字节序。对于无符号整数,它的计算方式如下(C 标准,6.5.7 按位移位运算符)
4 E1 <<E2 的结果是 E1 左移 E2 位位置;空出 位用零填充。如果 E1 具有无符号类型,则值 结果是 E1 × 2E2,比最大值多减少模一 可在结果类型中表示
即算术运算E1 × 2^E2。
所以例如表达式
1u << 1
等效于1u * 2
(1u * 2 ^ 1
)。