整数文字的类型和 C 中的 ~

Type of integer literals and ~ in C

我是一个C初学者,我被C答题簿上的下面这个例子弄糊涂了。

在您的系统上查找 unsigned long long 大小的一种方法是键入:

printf("%llu", (unsigned long long) ~0);

我不知道为什么这个语法有效?

在我的系统上,int 是 32 位,long long 是 64 位。
我期望的是,由于 0 是整数类型的常量,因此 ~0 计算 32 位整数的否定,然后由转换运算符将其转换为 unsigned long long。结果应该是 232 - 1。

不知何故,~ 运算符似乎已经知道它应该作用于 64 位?
编译器是否将此指令解释为 printf("%llu", ~(unsigned long long)0); ?这听起来不对,因为 cast 和 ~ 具有相同的优先级。

0int 类型,而不是 unsigned int~0 因此(在使用二进制补码整数表示的机器上,这是今天使用的所有整数表示形式)为 -1,而不是 232 - 1.

假设一个64位unsigned long long(unsigned long long) -1-1模264,即264 - 1.

0 是一个 int

~0 仍然是一个 int,即值 -1.

int 转换为 unsigned long long 仅仅是为了匹配 printf 期望的类型与转换 llu.

但是,-1 扩展的 unsigned long long 的值对于 4 字节 int 应该是 0xffffffff,对于 8 字节 int 应该是 0xffffffffffffffff。

Somehow, it looks like the ~ operator already knows that it should act on 64 bits?

这不是 ~ 运算符,而是强制转换。以下是根据标准进行整数转换的方式:

6.3.1.3 Signed and unsigned integers

  • When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
  • Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
  • Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

带符号的值 int ~0 对应于系统上的 -1 负值的补码表示。它不能用 unsigned long long 表示,因此第一个要点不适用。

第二个要点确实适用:新类型是无符号的,所以 unsigned long longMAX 被添加到 -1 一次,使结果进入 [=14] 的范围=].这与符号扩展 -1 到 64 位具有相同的效果。

根据 N1570 委员会草案:

6.5.3.3 Unary arithmetic operators

  1. The result of the ~ operator is the bitwise complement of its (promoted) operand (that is, each bit in the result is set if and only if the corresponding bit in the converted operand is not set). The integer promotions are performed on the operand, and the result has the promoted type. If the promoted type is an "unsigned type, the expression ~E is equivalent to the maximum value representable in that type minus E".

§6.2.6.2 Language 45:

(ones’ complement). Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones’ complement), is a trap representation or a normal value. In the case of sign and magnitude and ones’ complement, if this representation is a normal value it is called a negative zero.

因此,代码的行为:

printf("%llu", (unsigned long long) ~0);

在某些机器上是实现定义的和未定义的 - 不符合预期 - 取决于机器中整数的内部表示。

根据第 6.5.3.3 节,批准的代码编写方式为:

printf("%llu", (unsigned long long) ~0u);

此外,~0u 的类型是无符号整数,当您将其转换为 unsigned long long int 时,其格式字符串为 llu。使用格式字符串 %u.

打印 ~0u

要了解类型转换的基本概念,您可能喜欢阅读:What exactly is a type cast in C/C++?