我正在尝试将 char 中的所有位设置为 true。
char foo = 00000000;
foo |= 11111111;
for (int i = 0; i < 8; i++) { //prints out bitwise
printf("%d", !!((foo << i) & 0x80));
}
当 foo 全为 0 时,我得到 11000111。当 foo == 00000110 时,它打印 11001111;这里出了什么问题?
我正在尝试将 char 中的所有位设置为 true。
char foo = 00000000;
foo |= 11111111;
for (int i = 0; i < 8; i++) { //prints out bitwise
printf("%d", !!((foo << i) & 0x80));
}
当 foo 全为 0 时,我得到 11000111。当 foo == 00000110 时,它打印 11001111;这里出了什么问题?
该数字11111111
是十进制常数,而不是二进制。尽管您可以使用八进制或十六进制常量,但没有二进制常量(至少不是标准常量)。
如果您想要一个所有位都设置的数字,只需将按位补码运算符~
应用于 0:
unsigned char foo = ~0u;
unsigned char foo = ~0u;
, @dbush回答得很好,适用于:
unsigned char
char
那是无符号的。char
已签名并具有通常的实现定义的转换行为。char foo = ~0u;
调用实现定义的行为 (C111 6.3.1.3 3) 将超出范围设置为何unsigned
时char
有char
符号并且可能不会导致全为位模式。
第一个考虑:认识到在罕见的平台上全1char
是一个陷阱表达式。我们将假设这里不是这种情况。
请注意,对于罕见的符号幅度编码,全为位模式signed char
不会转换为全为位模式作为int
. 这可能会影响编码目标。
如果代码想要直接初始化 a char
(有 符号或无符号)并且不担心转换实现定义的行为,也不依赖于编码为 2 的补码、1 的补码或符号幅度,也不是范围或CHAR_BIT
值。
复合字面 量 C11
char mx1 = ( union { unsigned char uc; char c; } ) { .uc = -1u } .c;
联盟
const union {
unsigned char uc;
char c;
} ones = { -1u };
char mx2 = ones.c;
或者
// (-1 | -2) is a one's complement all one bits
// -1 is the two's complement all one bits
// CHAR_MIN is the sign-magnitude all one bits
char mx3 = (-1 | -2) | -1 | CHAR_MIN;
确定非 2 补码 的or值有点棘手,但通过分析它可以工作。
~0
// This may not work on rare sign-magnitude as it invokes implementation defined behavior
char mx4 = ~0;
将 char 设置为所有真位
#include <limits.h>
char all_ones = CHAR_MIN | CHAR_MAX;
在所有 char
位宽、char
符号和整数编码下都能正常工作1。
char
可能是有符号或无符号,如果有符号,它可能编码为 2 的补码,或者很少是一个补码或符号幅度。例子。它至少有 8 位,但在某些平台上它更宽。没有填充位。
本质上,我们正在寻找
char ones = CHAR_MAX; // `char` is unsigned
char ones = -1; // `char` is signed and 2's complement
char ones = ~0; // `char` is signed and 1's complement (rare)
char ones = CHAR_MIN; // `char` is signed and sign-magnitutde (rare)
将超出范围的值分配给char
已签名的解决方案会调用实现定义的行为。所以结果可能不是想要的所有结果。
否则,新类型是有符号的,值不能在其中表示;结果是实现定义的,或者引发了实现定义的信号。C11dr §6.3.1.3 3
// Almost always correct alternatives
char all_ones = ~0; // Work great but maybe not on rare sign-magnitude per 6.3.1.3 3
char all_ones = ~0u; // Always invokes 6.3.1.3 3 when char is signed.
1在稀有补码系统中,全为位模式可能是 -0 或陷阱。当一个陷阱,没有解决方案是可以接受的。
不要混淆十进制0
和1
与二进制0
和1
。当您分配11111111
给 时foo
,它是十进制基础文字而不是二进制文字。事实上,按照 C 标准,没有什么比二进制字面量更重要的了。虽然,一些编译器支持它作为扩展。如果要将 a 设置char
为所有 true ( 1
) 位,可以这样做:
foo = ~(foo & 0);