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

Jay*_*esh 44 c c++ bit-manipulation masking bit-masks

我看到下面的代码行这里的C.

 int mask = ~0;
Run Code Online (Sandbox Code Playgroud)

我已经打印了maskC和C++ 的值.它总是打印-1.

所以我确实有一些问题:

  • 为什么~0要为掩码变量赋值?
  • 目的是~0什么?
  • 我们可以用-1而不是~0吗?

Ric*_*ges 78

这是一种可移植的方法,可将所有二进制位整数设置为1位,而无需知道当前体系结构中的整数位数.

  • @LưuVĩnhPhúc正确.~0方法具有较少的依赖性.适用于未签名的非二人恭维系统,并且(可以说)不那么神秘. (25认同)
  • `-1`还将整数中的所有位设置为1,而不知道`int`类型的宽度.它只是意味着使用了两个补码 (7认同)
  • 如果在一个补码上,这是不可移植的:它给出负零,符合编译器可能决定的是陷阱表示.那时你有UB.公平地说,可以说这样的实现首先不具有'int`的全部值. (5认同)
  • @chqrlie为什么不呢?BTW使用有符号值的签名值是一个奇怪的想法. (3认同)

phu*_*clv 35

C和C++允许3种不同的有符号整数格式:符号幅度,1的补码和2的补码

~0无论系统使用何种符号格式,都将生成全部位.所以它比便携式更便携-1

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

1因为无符号运算总是以模数的形式减少,该数字大于结果类型可以表示的最大值


650*_*502 8

这对2的补平台(即假设)为您提供了-1,但写作-1直接由规则禁止(仅整数0..255,一元!,~和二元&,^,|,+,<<>>允许).


chq*_*lie 5

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

第一个问题是不使用-运算符的情况下返回值-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;
}
Run Code Online (Sandbox Code Playgroud)

文件中的其他问题并不总是正确实现.第二个问题,返回一个布尔值,表示一个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); 
}
Run Code Online (Sandbox Code Playgroud)

左移一个负值或移位值超出范围的数字int具有未定义的行为,右移一个负值是实现定义的,因此上述解决方案是不正确的(尽管它可能是预期的解决方案).