【问题标题】:How to insert booleans into a bitfield in C89如何在 C89 中将布尔值插入位域
【发布时间】:2018-03-25 18:54:56
【问题描述】:

据我了解,在 C89 中,所有布尔表达式都是整数类型。这也意味着表示 bool 的函数参数通常由 int 参数表示。

现在我的问题是,我怎样才能最理想地采用这样的int 并将其放入位域中,以便它只占用一位(现在让我们忽略填充)。

这里的第一件事是使用哪种类型。使用int 或任何其他无符号类型都不起作用,因为当只有一位时,只能表示-10(至少用二进制补码)。

虽然 -1 在技术上评估为 true,但这并不理想,因为据我了解,在没有未定义行为的情况下实际分配它可能非常棘手。

所以应该为位域选择无符号类型:

typedef struct bitfield_with_boolean {
    unsigned int boolean : 1;
} bitfield_with_boolean;

接下来的问题是如何分配该位域。仅采用 int 或类似的值是行不通的,因为向下转换会截断该值,因此如果未设置最低位,则先前计算为 true 的值现在会突然计算为 false

据我所知,布尔运算符保证总是返回01。所以我解决这个问题的想法是这样的:

#define to_boolean(expression) (!!(expression))

所以为了分配我会做的价值:

bitfield_with_boolean to_bitfield(int boolean) {
    bitfield_with_boolean bitfield = {to_boolean(boolean)};

    return bitfield;
}

这是正确的,还是有更好的方法?

注意:

我知道从 C99 开始问题已完全解决,因为保证转换为 _Bool 始终会导致 01。其中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


【解决方案1】:

是的,您的解决方案是正确的。但是,我不会将其隐藏在宏后面,也不会使用all_lowercase 字母命名宏。

!!var 足够地道,我会说它在代码中很好。

替代品包括var != 0,当然还有var ? 1 : 0

【讨论】:

  • 谢谢,这增加了我的信心 XD
  • @Jean-FrançoisFabre if (foo) 等同于 if (foo != 0)。 “那不是很好”是什么意思?
  • 0 是一个空指针常量。该代码在语义上是正确的,等效于!! 版本。
  • 我喜欢有一个宏,因为它允许我为不太熟悉 C 工作原理的代码读者记录我正在做的事情。我可以在宏旁边添加一条评论,说明为什么。
  • @FSMaxB 在这种情况下,我会使用标准的ALL_UPPERCASE 宏约定,例如#define TO_BOOL(X) (!!(X)).
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-07
  • 2011-08-28
  • 2011-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
相关资源
最近更新 更多