C - 将 ~0 转换为 unsigned long

Her*_*mit 8 c casting type-conversion

我\xe2\x80\x99见过低级按位表达式,用于~0生成所有s的位模式1,然后将其用作掩码等。例如在K&R第45页上:

\n
/* getbits: get n bits from position p */\nunsigned getbits(unsigned x, int p, int n)\n{\n    return (x >> (p+1-n)) & ~(~0 << n);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在我的机器上,(unsigned long) ~0计算结果为0x FF FF FF FF FF FF FF FF. 这让我们可以轻松生成1大于ints 的蒙版,这很好。

\n

但是,\xe2\x80\x99t 应该(unsigned long) ~0评估为 吗0x 00 00 00 00 FF FF FF FF?没有任何后缀,0被视为整数常量,因此~0计算结果为0x FF FF FF FF. 为什么 \xe2\x80\x99 不将其转换unsigned long为零填充值?我在这里缺少什么?

\n

编辑:在我的机器上,sizeof(int)sizeof(long)分别是 4 和 8。

\n

438*_*427 14

您的系统上~0有一个int位模式FF FF FF FF,表示十进制值 -1。

当转换为时,unsigned long您将一种整数类型转换为另一种整数。其规则可以在 C(草案)标准 n1570 的 6.3.1.3 中找到:

1 当一个整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则该值不变。

2 否则,如果新类型是无符号的,则通过在新类型可以表示的最大值上重复加或减 1 来转换该值,直到该值在新类型的范围内。60)

60) 规则描述了数学值的算术,而不是给定类型表达式的值。

第一条规则不适用,因为 -1 不能在 中表示unsigned long。应用第二条规则,即找到新值,如下所示

new-value = original-value + (ULONG_MAX + 1)
Run Code Online (Sandbox Code Playgroud)

在你的情况下:

new-value = -1 + (ULONG_MAX + 1) = ULONG_MAX
Run Code Online (Sandbox Code Playgroud)

所以新值是在您的系统上ULONG_MAX具有代表性的值FF FF FF FF FF FF FF FF

  • 添加一点细节:在进行这些转换时,方程应该作为纯粹的抽象数学来执行,而不考虑操作数的宽度。6.3.1.3 中有一个有用的脚注:“规则描述了数学值的算术,而不是给定类型表达式的值。” 也许将该注释添加到答案中以确保完整性。 (2认同)