This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器:bool 和 trap 表示法?

Guru**** 2193080 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/674651/compiler-bool-and-trap-representations

工具/软件:TI C/C++编译器

TI 编译器如何处理碰巧既不为0又不为1的_Bool 变量?

(您可以选择这种情况的发生方式:它们未初始化、键入打孔或其他副作用、宇宙辐射、即您所拥有的内容。)

我通常对 TI 的任何编译器目标的答案感兴趣、但我对 TI 的 ARM 编译器最感兴趣。

ARM 优化 C/C++编译器 v18.1.0.LTS 用户指南(spnu151r.pdf)对_Bool 没什么可说的、它恰好显示在3个位置、其中一个是表5-1中的条目、给出了255的"最大范围"。  我怀疑这有点误导。

用户指南中唯一提到"陷阱表示"的地方是第5.1.1节 J.3.5条中的一条语句、该语句指出"整数类型表示为二的补数、并且没有陷阱表示。"  我假设这仅指有符号整数类型、对吧?

TI 编译器是否会将读取既不是0也不是1的_Bool 变量视为未定义行为?

-thx

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、它是未定义的行为、因为该标准未定义在这种情况下应发生的情况。 实际上、bool 上的大多数操作都将其视为内置类型、并在测试时将其与零进行比较、因此它可能会像所有非零值都为 true 一样工作、这正是人们所期望的。 但是、我无法保证这一点始终为真。 很可能有很好的优化、假设如果_Bool 为 true、它正好为1。 是的、用户指南不应说它的最大范围为255。 是的、只有有符号整数表示为二进制补码。 无符号数是纯二进制值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    好的、很公平、谢谢。

    由于用户指南确实会指出(有符号)整数没有陷阱表示法、因此 UG 也会谨慎地指出_Bool 变量具有陷阱表示法、以及改善表5.1中的内容。

    这有点遗憾;bool 的引入对 C 语言的设计表现力进行了很好的改进、我们在许多地方都使用了它、但还有另一种方法可以进入 UB 是没有人的朋友。 我想我们将返回到 BOOL typedef 到 uint8_t (例如)。

    为了实现这一目的、我们观察到一个情况、即 TI ARM 编译器相信_bool 变量只能为0或1、在_bool 碰巧为0x81时生成的代码会产生令人惊讶的结果。

    -thx
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    从编译器的角度来看、使用_bool 类型声明变量是一个承诺、它实际上包含0或1。 如果这不是真的、例如您引用的值为0x81的情况、则不应将其声明为_Bool。 在其他上下文中仍然可以使用_Bool。 写入_bool 时、编译器将采取措施确保值为0或1。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我们正确地将变量声明为_Bool (实际上、我们在#include stdbool.h 之后将其声明为"bool)、这是因为我们的意图是它只会为0或1、并将其声明为 bool 表示该意图。

    我们还认为我们喜欢这样的功能:对 bool 的赋值(包括向 bool 函数参数提供非 bool 整数)会自动将非零整数转换为1。  我们只是没有深入研究从 bool 读取数据时是否发生类似转换的问题。  这并不令人惊讶;只是我们没有真正理解、通过使用 C99标准_Bool / bool 类型、我们一直面临一个新类别的漏洞(陷阱表示)、而该类别在其他方面不存在。

    其值设法为0x81的情况是一个错误。  (大概是我们的错误、但不一定;我们尚未跟踪它。)  无论我们使用哪种类型的变量、都需要对其进行修复。

    但是、要使程序安全、不仅仅是找到所有错误并修复它们。  很难解释未定义的行为。  执行以下函数:

    #ifdee_undefined_behavior
    typedef unsigned char BOOL;
    #else
    typedef _bool BOOL;
    #endif
    
    void checkStatus (BOOL errorDetected)
    {
    IF (错误检测)
    handleError();
    其他
    HandleSuccess();
    }
    

    可以很容易地想象,开发人员或对等审校员可能会假定,无论 BOOL 是以何种方式定义的,在每次调用 checkStatus()时(但不是两者都定义!) 将调用 errorDetected ()或 handleSuccess(),而不管程序执行早期可能发生了什么类型的错误。

    这当然是天真的。  C 语言中有超过一百种未定义的行为、更不用说堆栈损坏或其他严重的"外部"问题的可能性。  如果 handleError()和 handleSuccess()都没有被调用,或者两者都被调用,那么,这并不是发生未定义行为时可能发生的最糟糕的事情。

    但是、将 BOOL 定义为_Bool 会增加一个额外的基本漏洞、当 BOOL 定义为 unsigned char 时、它不具有该漏洞。

    (对于这种情况、使用 unsigned char 将允许我们添加断言检查以确认 errorDetected 始终为0或1。)

    (我并不是说我们检测到 TI ARM 编译器以令人惊讶的方式编译了上述函数。  我们的实际惊喜是位字段。  我将对其进行一些简化、并将其添加到此线程中、就像 FYI 一样、如果有人有任何好奇、我接受编译器符合适用的 C 标准。)

    -thx

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、不幸的是、有如此多的未定义行为区域、但它们通常是由 C 标准引起的、不想过多地指定实现、通常是为了可以对优化进行假设。 有人可能会争辩说、这不是最安全的事情、但语言就是它的样子...