C:为什么&=比=更好?

时间:2020-01-09 14:26:01

标签: c assembly compiler-optimization

我正在查看我继承的一些旧代码,我真的不喜欢某些地方的样式。我真的不喜欢它的外观之一是:

bool func() {
    bool ret = true;

    ret &= test1();
    homemade_assert_like_function(ret == true);
    ret &= test2();
    homemade_assert_like_function(ret == true);

    return ret;
}

我认为以下内容更清晰:

bool func() {
    homemade_assert_like_function(test1());
    homemade_assert_like_function(test2());

    return true; // just to keep the interface
}

但是,后者会产生更多的汇编代码。毫不奇怪,如果我将第一个示例中的&=更改为=,则结果与assert(test());相同,但是&=似乎仍然更好

对于所有三个示例,我都将gcc5.4用于带-O2的mips,但是如果对pc使用gcc,则结果是相似的。如果我使用-std = c ++ 14(和更新的编译器)进行编译,则这三个示例将生成相同的代码。

有人可以向我解释吗?仅仅是我的测试代码真的很糟糕吗?

编辑: 我制作了一个新的代码示例,修复了损坏的断言。它确实有一个有趣的副作用。现在,大小差异要小得多,这向我表明,优化器必须能够在&=情况下发挥某些作用。

https://godbolt.org/z/Vk6uoY

正如已经多次指出的那样,示例代码有些模糊。但它显示出的效果与我在真实代码中看到的效果相同-除了删除&=代码风格之外,什么都不做,只会增加代码库。

2 个答案:

答案 0 :(得分:3)

此代码正在尝试以使用快捷方式评估,但失败。
(代码错误)

首先,让我展示一下 meant 要做的事情:

代码应为:

bool func() {
    bool ret = true;

    ret = ret && test1();
    homemade_assert_like_function(ret == true);

    ret = ret && test2();
    homemade_assert_like_function(ret == true);

    return ret;
}

重要的是,如果ret已经是false,表明结果失败了,它甚至不会尝试计算表达式的第二部分! (test1()test2())。

如果函数test()有任何副作用,则一旦ret标志指示失败后,它将不会运行。

这对于经历漫长的多步骤过程(test1() ... testN())很有用,并且一旦单个步骤失败就不再执行任何工作。


现在,这段代码实际上在做什么,为什么?

rettrue开始,一旦其中一个功能失败,ret就会变为false,并停留在false(只要操作始终为&=。 / p>

但是,与我之前写的不同,即使先前的测试已经失败,每个函数test1()test2()testN()仍然可以运行(包括副作用)!

这与他们将代码编写为:

bool func() {
    bool ret = true;

    ret = test1();
    homemade_assert_like_function(ret == true);
    ret = test2();
    homemade_assert_like_function(ret == true);

    return ret;
}

与您建议的代码的最大区别是您的代码 始终 返回true。您如何假设每个测试都成功?测试失败时,应允许代码返回false。您从代码版本中删除了该功能。

答案 1 :(得分:-1)

我认为这是不必要的复杂测试代码。如果仅反汇编该函数本身,就会发现对该函数的外观更改导致接近相同的代码。实际上,它们会导致代码更快。

我摆脱了所有毫无意义的混淆,写了一个可读的版本:

#include <stdbool.h>

bool func (void) {
    assert(test1());
    assert(test2());
    return true;
}

关于gcc x86-64 9.2 -O2的11条说明。但是您的原始版本提供了15条说明。将函数类型更改为bool会导致代码稍有不同,但是干净版本仍然更有效。

https://godbolt.org/z/4Cmr_H

然而,这里的重要部分是编写可读性最高的代码。像bool ret = true; ret &= test1();这样的怪异事物简直是毫无意义的。

相关问题