【发布时间】:2018-03-25 18:54:56
【问题描述】:
据我了解,在 C89 中,所有布尔表达式都是整数类型。这也意味着表示 bool 的函数参数通常由 int 参数表示。
现在我的问题是,我怎样才能最理想地采用这样的int 并将其放入位域中,以便它只占用一位(现在让我们忽略填充)。
这里的第一件事是使用哪种类型。使用int 或任何其他无符号类型都不起作用,因为当只有一位时,只能表示-1 和0(至少用二进制补码)。
虽然 -1 在技术上评估为 true,但这并不理想,因为据我了解,在没有未定义行为的情况下实际分配它可能非常棘手。
所以应该为位域选择无符号类型:
typedef struct bitfield_with_boolean {
unsigned int boolean : 1;
} bitfield_with_boolean;
接下来的问题是如何分配该位域。仅采用 int 或类似的值是行不通的,因为向下转换会截断该值,因此如果未设置最低位,则先前计算为 true 的值现在会突然计算为 false。
据我所知,布尔运算符保证总是返回0 或1。所以我解决这个问题的想法是这样的:
#define to_boolean(expression) (!!(expression))
所以为了分配我会做的价值:
bitfield_with_boolean to_bitfield(int boolean) {
bitfield_with_boolean bitfield = {to_boolean(boolean)};
return bitfield;
}
这是正确的,还是有更好的方法?
注意:
我知道从 C99 开始问题已完全解决,因为保证转换为 _Bool 始终会导致 0 或 1。其中0 仅是输入值为0 时的结果。
【问题讨论】:
-
是的
(!!(expression))是经典的布尔转换。 -
旁注:不要使用过时的非标准 C。正如您所写,C99 提供了布尔类型(尽管出于兼容性原因,逻辑表达式仍会生成
int结果)。如果您的 rtoolchain 不支持 C11(或至少 C99),请获取现代编译器。关于。一般位域:不要使用它们。请改用位操作。几乎所有关于位域的内容都是特定于实现的,包括int位域是有符号还是无符号。它们被设计破坏了。 -
@Olaf ... 如果可以,我根本不会使用 C,我会使用 Rust。或者可能是 C++17 而不是 C89。只是在现实世界中,有时存在一些远非理想的约束。
-
C11 很好,C99 可以接受(尽管我希望他们因此而更多地切断了遗产)。用核武器射击麻雀也没有用。到目前为止,对于大多数项目来说,至少有一种合理的方式可以使用 C99,这与 C11 的非可选部分基本相同。仍然使用 C90 的原因是“开发人员”对新开发的完全无知,不想学习新东西。不幸的是,他们中的一些人从未系统地了解过这些陷阱,因此他们的代码调用了 UB。这也是他们抱怨现代编译器“破坏”他们的代码的原因(恰恰相反)。
-
@Olaf 幸好 MSVC 直到最近才支持 C99。还有一些嵌入式工具链卡在 C89 上。
标签: c boolean bit-fields c89