c语言 - 左移运算符是否将钻头包裹起来?



如果我对左移运算符和小端的理解是正确的,那么下面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)。

最新更新