如何在 c 中计算 printf("%c\n",~('C'*-1)) ?
How printf("%c\n",~('C'*-1)) is computed in c?
#include<stdio.h>
int main()
{
printf("%c\n",~('C'*-1));
return 0;
}
上面的源码我已经试过了,没有任何警告就执行了。
输出为B。
我很兴奋上面的代码是如何处理的以及 printf("%c\n",~('C'*-1))
的含义是什么
在C语言中,'C'
是一个int
,它是一个小整数,值为67
(假设为ASCII)。您可以从以下位置获取每个步骤:
#include<stdio.h>
int main()
{
printf("%d\n", 'C'); //67
printf("%d\n", 'C' * -1); //-67
printf("%d\n", ~('C' * - 1)); //66
printf("%c\n",~('C' * -1)); //B
return 0;
}
在2的补码中,~(-67)
的值为66
。
唯一重要的部分是这个表达式:
~('C' * -1)
让我们分解一下:
'C'
是 ASCII 代码 67.
('C' * -1)
是-67.
- -67 在二进制中是 10111101
- 按位取反(
~
),得到 01000010,即 66。
- 66 是 'B'.
的 ASCII 码
更一般地说,大多数计算机使用“two's complement”算术,其中数值取反后按位取反相当于减 1。当然 B
比 C
少一在 ASCII 中。
在不使用补码运算的计算机上,结果可能会有所不同。这样的电脑很少见。
众所周知,"making a number negative"(将其乘以 -1
)的二进制补码相当于反转其位表示形式 (~
) 并加一 (+1
).因此,上面等价于 ~(~'C' + 1)
,如果原始数字(如这里的 'C'
的 ASCII 代码)为奇数,则又相当于简单的递减。
即如果设置了'C'
的LSB:
~'C'
的LSB没有设置,也就是说
- 加一 (
~'C' + 1
) 后,LSB 再次设置。
- 现在反转整个表达式 (
~(~'C' + 1)
) 将为我们提供原始数字 - 只是不再设置 LSB,因为它是在最终反转之前设置的(像其他位一样反转 LSB) .
同上简化一下
- 'C' 十进制为 67,二进制为 01000011
- ('C'*-1) 在十进制中是 -67 而在二进制中我们必须取 67 的补码
并在其补码中加 1 = 10111100 +1 = 10111101
- ~('C'*-1) 是 -67 的否定,即 10111101 的恭维是
01000010 在十进制中是 66 在 ascii 中是 'B'
#include<stdio.h>
int main()
{
printf("%c\n",~('C'*-1));
return 0;
}
上面的源码我已经试过了,没有任何警告就执行了。
输出为B。 我很兴奋上面的代码是如何处理的以及 printf("%c\n",~('C'*-1))
的含义是什么在C语言中,'C'
是一个int
,它是一个小整数,值为67
(假设为ASCII)。您可以从以下位置获取每个步骤:
#include<stdio.h>
int main()
{
printf("%d\n", 'C'); //67
printf("%d\n", 'C' * -1); //-67
printf("%d\n", ~('C' * - 1)); //66
printf("%c\n",~('C' * -1)); //B
return 0;
}
在2的补码中,~(-67)
的值为66
。
唯一重要的部分是这个表达式:
~('C' * -1)
让我们分解一下:
'C'
是 ASCII 代码 67.('C' * -1)
是-67.- -67 在二进制中是 10111101
- 按位取反(
~
),得到 01000010,即 66。 - 66 是 'B'. 的 ASCII 码
更一般地说,大多数计算机使用“two's complement”算术,其中数值取反后按位取反相当于减 1。当然 B
比 C
少一在 ASCII 中。
在不使用补码运算的计算机上,结果可能会有所不同。这样的电脑很少见。
众所周知,"making a number negative"(将其乘以 -1
)的二进制补码相当于反转其位表示形式 (~
) 并加一 (+1
).因此,上面等价于 ~(~'C' + 1)
,如果原始数字(如这里的 'C'
的 ASCII 代码)为奇数,则又相当于简单的递减。
即如果设置了'C'
的LSB:
~'C'
的LSB没有设置,也就是说- 加一 (
~'C' + 1
) 后,LSB 再次设置。 - 现在反转整个表达式 (
~(~'C' + 1)
) 将为我们提供原始数字 - 只是不再设置 LSB,因为它是在最终反转之前设置的(像其他位一样反转 LSB) .
同上简化一下
- 'C' 十进制为 67,二进制为 01000011
- ('C'*-1) 在十进制中是 -67 而在二进制中我们必须取 67 的补码 并在其补码中加 1 = 10111100 +1 = 10111101
- ~('C'*-1) 是 -67 的否定,即 10111101 的恭维是 01000010 在十进制中是 66 在 ascii 中是 'B'