将 char 设置为所有真位

Setting char to all true bits

我正在尝试将 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;

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

foo = ~(foo & 0);

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

  1. unsigned char
  2. charunsigned.
  3. charsigned 并且具有 usual 实现定义的转换行为。

char foo = ~0u; 调用实现定义的行为 (C111 6.3.1.3 3),当 char 为 [=48 时,将超出范围的 unsigned 设置为 char =]signed 并且可能不会产生全 1 位模式。


首先考虑:认识到在罕见的平台上,全一 char 是陷阱表达式。我们假设情况并非如此。

请注意,使用罕见的符号幅度编码,signed char 的全 1 位模式不会转换为 int 的全 1 位模式。这可能会影响编码目标。


如果代码想直接初始化一个 charsignedunsigned)而不用担心定义的转换实现行为,也不依赖编码作为 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 的补码的 值有点棘手,但通过分析它是可行的。

~0

// This may not work on rare sign-magnitude as it invokes implementation defined behavior
char mx4 = ~0;

Setting char to all true bits

#include <limits.h>
char all_ones = CHAR_MIN | CHAR_MAX;

在所有 char 位宽、char 符号和整数编码下都能正常工作1.


char可能是signedunsigned,如果signed,则可以编码为 2 的补码,或者很少编码为 1 的补码或符号大小。 Examples。它至少有 8 位,但在 select 平台上它更宽。没有填充位。

本质上,我们在寻找

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的解决方案会调用实现定义的行为。所以结果可能不是所有想要的结果。

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. 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在罕见的 one`s complement 系统中,全 1 位模式可能是 -0 或陷阱。当陷阱时,无解。