C++ 将布尔隐式转换为 int 和算术,删除分支,找不到错误

C++ implicit cast bool to int and arithmetic, removing branches, can't find bug

本文关键字:删除 分支 错误 找不到 布尔隐 转换 int C++      更新时间:2023-10-16

在C 中删除分支,无法在输出后面解密推理。

PopHi()采用两个向上排序的ints和到目前为止最大的索引的两个向量。它通过减少两者中较大的索引来"弹出"所有人的最大int。

代码

原始:

void PopHi(vector<int> &arrA, vector<int> &arrB, int &idxHiA, int &idxHiB) {
    int hi = max(arrA[idxHiA], arrB[idxHiB]);
    if (hi == arrA[idxHiA])
        --idxHiA;
    else
        --idxHiB;
}

Nobranch版本1:

void PopHi(vector<int> &arrA, vector<int> &arrB, int &idxHiA, int &idxHiB) {
    idxHiA -= (arrA[idxHiA] > arrB[idxHiB]);
    idxHiB -= (!(arrA[idxHiA] > arrB[idxHiB]));
}

NobRanch版本2,因为如果它们相等,我们选择哪一个都不重要:

void PopHi(vector<int> &arrA, vector<int> &arrB, int &idxHiA, int &idxHiB) {
    idxHiA -= (arrA[idxHiA] >= arrB[idxHiB]);
    idxHiB -= (!(arrA[idxHiA] >= arrB[idxHiB])); // extra paranoia parens
}

这就是我的使用方式:

// compiled with g++ -std=c++11 main.cpp -o run
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
    vector<int> arrA({1, 3, 5});
    vector<int> arrB({5});
    int idxHiA = 2;
    int idxHiB = 0;
    cout << idxHiA << ", " << idxHiB << endl;
    PopHi(arrA, arrB, idxHiA, idxHiB);
    cout << idxHiA << ", " << idxHiB << endl;
    return 0;
}

输出

原始:

2, 0
1, 0 // ok

版本1:

2, 0
2, -1 // also ok

版本2:

2, 0
1, -1 // wtf??
idxHiA -= (arrA[idxHiA] >= arrB[idxHiB]);

您正在此处更改idxHiA ...

idxHiB -= (!(arrA[idxHiA] >= arrB[idxHiB]));

...在这里咬你。您想使用idxHiA的旧值,但正在使用降低的值(可能是非法的BTW)。该位置的元素不再是最大值。

我建议将比较与布尔变量进行比较的结果,这更清楚地读取。

ps:我会在汇编器中检查您的"无分支"版本实际上是没有分支机构的。有时,使用分支进行布尔变量的操作。