首页 > 解决方案 > 将 long 转换为 int 与使用按位 AND 以获得 4 个最低有效字节之间有什么区别?

问题描述

我知道,为了获得多种类型的 4 个最低有效字节,long我可以将其转换为int/unsigned int或使用按位 AND ( & 0xFFFFFFFF)。

代码产生以下输出:

#include <stdio.h>

int main()
{
  long n = 0x8899AABBCCDDEEFF;
  printf("0x%016lX\n", n);
  printf("0x%016X\n", (int)n);
  printf("0x%016X\n", (unsigned int)n);
  printf("0x%016lX\n", n & 0xFFFFFFFF);
}

输出:

0x8899AABBCCDDEEFF
0x00000000CCDDEEFF
0x00000000CCDDEEFF
0x00000000CCDDEEFF

这是否意味着使用的两种方法是等效的?如果是这样,无论平台/编译器如何,它们是否总是产生相同的输出?
此外,在投射到unsigned int而不是int为了这个问题的目的时是否有任何捕获或陷阱?最后,如果将数字改为 an
,为什么输出相同?nunsigned long

标签: c++castingbit-manipulationbitwise-and

解决方案


将 long 转换为 int 与使用按位 AND 以获得 4 个最低有效字节之间有什么区别?

类型。强制转换使值成为int. And'ing 不改变类型。

范围。根据int,long范围,强制转换可能根本不会改变值。

美洲开发银行和 UB。实现定义的行为未定义的行为以混合符号存在。

要“获取” 4 个 LSByte,请使用& 0xFFFFFFFFu或强制转换为uint32_t.


OP的问题不必要地令人费解。

long n = 0x8899AABBCCDDEEFF;--> 转换有符号整数类型范围之外的值是实现定义的

否则,新类型是有符号的,值不能在其中表示;结果是实现定义的,或者引发了实现定义的信号。
C11 §6.3.1.3 3

printf("0x%016lX\n", n);long-->使用"%lX"超出常见范围的a打印 along/unsigned long未定义的行为


让我们继续unsigned long

  unsigned long n = 0x8899AABBCCDDEEFF;  // no problem,
  printf("0x%016lX\n", n);               // no problem,
  printf("0x%016X\n", (int)n);           // problem, C11 6.3.1.3 3
  printf("0x%016X\n", (unsigned int)n);  // no problem,
  printf("0x%016lX\n", n & 0xFFFFFFFF);  // no problem,

“没问题”即使是unsigned long32 位或 64 位也可以。输出会有所不同,但还可以。

回想一下,int,long并不总是 32,64 位。(16,32), (32,32), (32,64) 很常见。

int至少为16位。至少
long32位的。int



推荐阅读