"int mask = ~0;" 的目的是什么?

What is the purpose of "int mask = ~0;"?

我在 C 中看到了下面这行代码 here

 int mask = ~0;

我已经在 C 和 C++ 中打印了 mask 的值。它总是打印 -1.

所以我有一些问题:

这是一种可移植的方式,可以将整数中的所有二进制位设置为 1 位,而无需知道当前架构中整数中有多少位。

C 和 C++ 允许 3 种不同的有符号整数格式:符号大小、一个补码和两个补码

~0 将生成全 1 位 ,而不管系统使用的符号格式如何。所以它-1

更便携

您可以添加 U 后缀(即 -1U)以生成全 1 位模式 可移植1。然而 ~0 表明意图更清楚 :反转值 0 中的所有位,而 -1 将表明需要负一的值,而不是其二进制表示

1 因为无符号运算总是 reduced modulo the number that is one greater than the largest value that can be represented by the resulting type

在 2 的补码平台上(假设)给你 -1,但规则禁止直接写 -1(仅整数 0..255,一元 !~ 和二进制 &^|+<<>> 是允许的)。

在所有计算机体系结构中都有多种编码数字的方法。当使用 2 的补码时,这将始终为真:~0 == -1。另一方面,一些计算机使用 1 的补码来编码负数,而上面的例子是不正确的,因为 ~0 == -0。是的,1s 补码有负零,这就是为什么它不是很直观。

所以对于你的问题

  • 将 ~0 分配给掩码,因此掩码中的所有位都等于 1 -> 使 mask & sth == sth
  • 无论使用何种平台,~0 用于使所有位都等于 1
  • 如果您确定您的计算机平台使用 2 的补码编码,您可以使用 -1 而不是 ~0

我个人的想法 - 让你的代码尽可能独立于平台。成本相对较小,代码成为fail proof

您正在研究一项编码挑战,其中对执行给定任务的运算符和语言结构有许多限制。

第一个问题是 return 值 -1 没有使用 - 运算符。

在用二进制补码表示负数的机器上,值 -1 的所有位都设置为 1,因此 ~0 的计算结果为 -1

/* 
 * minusOne - return a value of -1 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 2
 *   Rating: 1
 */
int minusOne(void) {
  // ~0 = 111...111 = -1
  return ~0;
}

文件中的其他问题并不总是正确执行。第二个问题,returning 一个布尔值表示 int 值适合 16 位带符号 short 的事实有一个缺陷:

/* 
 * fitsShort - return 1 if x can be represented as a 
 *   16-bit, two's complement integer.
 *   Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 1
 */
int fitsShort(int x) {
  /* 
   * after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
   * so after shift, if x remains the same, then it means that x can be represent as 16-bit
  */
  return !(((x << 16) >> 16) ^ x); 
}

左移负值或移位值超出int范围的数字有未定义的行为,右移负值是实现定义的,所以上面的解决方案是不正确的(虽然它可能是预期的解决方案)。

很久以前,这就是您在极其有限的设备(例如 1K ZX 80 或 ZX 81 计算机)上节省内存的方式。在 BASIC 中,你会

Let X = NOT PI

而不是

LET X = 0

由于数字存储为 4 字节浮点数,后者比第一个 NOT PI 替代方案多占用 2 个字节,其中 NOT 和 PI 各占用一个字节。