作为给定三个数字的建议解决方案,找到其中第二大的数字,我写道:
int second_largest(int a, int b, int c) {
int smallest = min(min(a, b), c);
int largest = max(max(a, b), c);
/* Toss all three numbers into a bag, then exclude the
minimum and the maximum */
return a ^ b ^ c ^ smallest ^ largest;
}
这个想法是^ smallest ^ largest
取消位,以便保留中间数字。
但是,@chux 指出了一个问题:
int
和的一个独特问题a ^ b ^ c ^ smallest ^ largest
是中间结果可能是罕见的非 2 补码平台上的陷阱表示。– 楚克斯@chux请解释一下?XOR 只是逐位运算,并不关心位代表什么,对吧?– 200_成功
XOR 不在乎,但结果可能是一个问题:例如,使用符号幅度整数,可能
-1 ^ 1
会-0
出现一个陷阱值 - 停止代码。参见 C11 §6.2.6.2 2. 位运算更好地用于无符号类型。– 楚克斯进一步的 C11 §6.2.6.2 3 在罕见的非 2 的补码平台上指定 ^ 的实现定义行为 int 。特别是“未指定这些情况是否实际生成负零或正常零”,渲染 a ^ b ^ c ^ minimum ^ maximum 未指定即使不使用陷阱值它也会按需要工作。下一节将解释这如何成为 UB。最好将这个新颖的代码留给无符号类型。– 楚克斯
不幸的是,一种在逻辑上和数学上应该是合理的技术可能会因技术性而脱轨。
有没有办法挽救这种 XOR 技术并使其合法安全,理想情况下运行时开销为零?(可能涉及工会的事情?)