C 三值运算是否在编译时执行?

C 三值运算是否在编译时执行?,c,performance,ternary-operator,C,Performance,Ternary Operator,我正在用C从头开始制作一个基于比特板的国际象棋引擎。移动生成过程对时间特别敏感。目前,我的代码如下: void generate_moves(Position *p, Colour side, Move *list) { if(side == WHITE) { Bitboard b1 = p->piece_bitboards[BLACK_KNIGHT]; Bitboard top_rank_mask = MASK_RANK[RANK8];

我正在用C从头开始制作一个基于比特板的国际象棋引擎。移动生成过程对时间特别敏感。目前,我的代码如下:

void generate_moves(Position *p, Colour side, Move *list) {
    if(side == WHITE) {
        Bitboard b1 = p->piece_bitboards[BLACK_KNIGHT];
        Bitboard top_rank_mask = MASK_RANK[RANK8];
        ...
    } else {
        Bitboard b1 = p->piece_bitboards[WHITE_KNIGHT];
        Bitboard top_rank_mask = MASK_RANK[RANK1];
        ...
    }
}
以及其他几百行代码,它们要么是黑白镜像的,要么是相同的。然而,对我来说,这似乎是一个容易出现错误和困惑的问题

因此,在每个fork处使用三元运算符替换大型if-else以提高可读性:

void generate_moves(Position *p, Colour side, Move *list) {
    Bitboard b1 = p->piece_bitboards[side == WHITE ? WHITE_KNIGHT : 
        BLACK_KNIGHT];
    Bitboard top_rank_mask = MASK_RANK[side == WHITE ? RANK8 : RANK1];
    ...
}

有类似的表现吗?所有三元运算符都依赖于变量端,变量端只能假定常量值为白色或黑色。

任何中等质量的编译器都会将两个代码序列视为相同的,除非禁用优化

第二个序列名义上有两个或多个测试,但是编译器应该识别重复的表达式以及它不能从一个语句更改到下一个语句的事实,因为其中的操作数不受前一个语句中的任何内容的影响(
Bitboard b1=p->piece\U bitboards[side==WHITE?WHITE\U KNIGHT:
黑色骑士];
)。(大概白色是一个常量。)即使是中等质量的编译器也需要这样的优化

至于是在编译时进行选择(选择
if
序列中的两个块中的一个,还是在另一种情况下选择三值操作数),除非编译器知道
side
的值,否则无法进行选择。由于
side
是一个函数参数,编译器无法仅从函数的源代码中知道其值。如果编译器可以看到调用函数的位置,并且为
端传递的参数是一个常量表达式,或者可以由编译器以其他方式推导,那么它就可以知道它的值。例如,如果调用代码包含两个序列,其中一个调用
generate_moves
用于
WHITE
,另一个调用
generate_moves
用于
BLACK
,编译器可能会为
generate_moves
生成内联代码,其中选择在每种情况下都已优化

在什么情况下可以这样做就不那么清楚了,更多地取决于编译器和其他代码的属性,您还没有展示这些属性


像这样的代码中的性能受其他因素的影响可能比您确定的条件选择要大得多。

它们不可能在编译时完成,因为它们依赖于运行时变量。您已将一个分支替换为数百个分支。当然,它应该以(性能)为代价。作为旁注,我想说,似乎没有任何好的理由对这个问题投反对票。很好。