3

看看这个例子:

unsigned char c = 64; /* 0100 0000 */
c = (c << 2 && 512); /* 512: 10 0000 0000  */

如果我将 c 向左移动两次,我应该从 0100 0000 (64) 到这个 0001 0000 0000 (256)。所以我的 8 位字符c只有零。最后,我想知道为什么表达式(c << 2 && 512)为真 (1) 而不是假 (0),因为我的 c 只有零。

4

3 回答 3

3

来自 C 标准(6.5.7 位移位运算符)

3 对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。

所以在这个表达式中

c << 2

对象 c 被提升为 typeint并且结果也具有 type int

由于逻辑 AND 运算符的两个操作数都不等于,0因此整个表达式的计算结果为1

来自 C 标准(6.5.13 逻辑与运算符)

3 如果 && 运算符的两个操作数比较不等于 0,则 && 运算符将产生 1;否则,它产生 0。结果具有 int 类型。

您似乎将逻辑运算符 AND&&与按位运算符 AND混淆了&

如果你会写

c = (c << 2 & 512);

那么变量c的值为0。

于 2022-01-13T18:20:03.100 回答
2

&是按位与。结果中的每一位都是其输入中两个对应位的与。01 0000 0000 2和 10 0000 0000 2的按位与将是 00 0000 0000 2

&&是逻辑与。如果两个操作数都不为零,则其结果为 1,否则为 0。01 0000 0000 2和 10 0000 0000 2的逻辑与为 1。

于 2022-01-13T18:19:26.903 回答
2

弗拉德的答案是解释。
这是一个可视化,在存在提升的情况下将某些东西放入特殊数据类型是多么困难:

#include <stdio.h>

int main()
{
    printf("Hello, World!\n");
    
    unsigned char c = 64;
    
    if (c <<   2 ) {printf("Yes 1.\n");}
    if (c << '\2') {printf("Yes 2.\n");}
    if ((unsigned char)(c << 2)) {printf("Yes 3.\n");} else {printf(" No 3.\n");}
    if ((unsigned char)(c) << (unsigned char)(2)) {printf("Yes 4.\n");} else {printf(" No 4.\n");}
    

    return 0;
}

输出(例如这里https://www.tutorialspoint.com/compile_c_online.php):

Hello, World!
Yes 1.
Yes 2.
 No 3.
Yes 4.

您的代码中的版本在 1 中失败。
尝试使用 unsigned char 操作数的版本在 2 中失败。
只有 3,操作后的显式转换设法覆盖提升。
While 4,尝试在操作之前对操作数使用显式强制转换再次失败。

于 2022-01-13T18:29:19.850 回答