让 bool 方法返回其他整数

Posted

技术标签:

【中文标题】让 bool 方法返回其他整数【英文标题】:Let a bool method return other integer 【发布时间】:2020-02-16 06:40:34 【问题描述】:
class I 
public:
    virtual bool F() = 0;
;

class A :public I 
public:
    virtual bool F() 
        int i = 2;
        return i;
    
;

void test()    
    A a;
    int i=a.F();
    std::cout << i;

class I 是一个不易更改的协议。

想要传递比真/假更多的信息,所以想在 C++ 中使用 bool 的 uint8_t 属性。

但是编译器(VS2019/VS2017)在返回之前在 bool 方法的末尾添加了将整数转换为 0 或 1 的指令。调用方没有转换(只有一个 movzx eax, al 指令),这很好。

在bool方法的末尾有没有像编译标志或者一些嵌入的汇编代码这样的方法,让bool方法返回0/1以外的整数?

【问题讨论】:

如果您更改 A 中的覆盖可以返回的值,则需要调整 F() 的每个调用站点以处理返回值的更改,因为它可能会调用 F on一个A。因此,无论如何您都必须更改F() 的每次使用,因此您可以通过更改AI 中声明的返回类型以相同的工作量来干净地完成它。 @walnut 这是基于任何现有调用者使用返回值作为布尔值的猜测。这个猜测很有可能是真的。我们现在可以假设它是真的吗? 取决于 ABI 如何定义 bool 值的传递,调用者可以假设传递的寄存器/堆栈位置保证只包含值零或一。如果您违反此保证,则程序可能无法正常运行。看看this recent reddit post 准确描述了这样一个bool 错误以及调试的难度。 我不知道 Windows ABI 对此有什么特别要说的,也许你很幸运,这在技术上是可行的,但无论如何我强烈建议不要使用这种诡计。 @walnut 谢谢你的提醒,会关心这个。现在真的想以某种方式完成这项工作,而不是生产系统。现在更改协议的主要问题是:甚至很难找到更改的位置,并且可能会出现编译错误的噩梦。您确定更改协议不会引发错误吗? 【参考方案1】:

简单的免责声明是,这个答案对生产使用没有好处。它使用通常未定义的行为。

您可以使用 reinterpret_cast 将返回值转换为布尔值,而无需实际触发 bool 构造函数(因此不会将实际值更改为 0/1)。

class A :public I 
public:
    virtual bool F() 
        int i = 2;
        return *reinterpret_cast<bool *>(&i);;
    
;

【讨论】:

以上是关于让 bool 方法返回其他整数的主要内容,如果未能解决你的问题,请参考以下文章

在 bool 函数中返回 true 或其他内容

方法 BOOL 从内部块返回

isEqualToString 总是返回 False

Bool 方法返回错误值

使用 != 了解返回 BOOL 的方法

如何解决 bool 方法上的“并非所有代码路径都返回值”?