2

我正在尝试将 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;这里出了什么问题?

4

4 回答 4

8

该数字11111111是十进制常数,而不是二进制。尽管您可以使用八进制或十六进制常量,但没有二进制常量(至少不是标准常量)。

如果您想要一个所有位都设置的数字,只需将按位补码运算符~应用于 0:

unsigned char foo = ~0u;
于 2018-02-08T21:15:14.560 回答
1

unsigned char foo = ~0u;, @dbush回答得很好,适用于:

  1. unsigned char
  2. char那是无符号的。
  3. char签名并具有通常的实现定义的转换行为。

char foo = ~0u;调用实现定义的行为 (C111 6.3.1.3 3) 将超出范围设置为何unsignedcharchar符号并且可能不会导致全为位模式。


第一个考虑:认识到在罕见的平台上全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;
于 2018-02-08T23:01:44.553 回答
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 或陷阱。当一个陷阱,没有解决方案是可以接受的。

于 2018-02-09T16:07:53.643 回答
0

不要混淆十进制01与二进制01。当您分配11111111给 时foo,它是十进制基础文字而不是二进制文字。事实上,按照 C 标准,没有什么比二进制字面量更重要的了。虽然,一些编译器支持它作为扩展。如果要将 a 设置char为所有 true ( 1) 位,可以这样做:

foo = ~(foo & 0);
于 2018-02-08T22:22:21.110 回答