C について話していて、どうしようもない場合は、次のようにします。
if(何とか) 数 += (1<<n);
Cには実際にはブール値はなく、そうである必要もありません。falseはゼロで、trueはゼロではないため、ソリューションに必要なゼロではない1であると仮定することはできません。また、特定の何とかビットが設定されています。たとえば、次のようになります。
number += (何とか&1)<<n;
0x2 または 0x4、またはビット 0 をクリアしたゼロ以外のものは true と見なされるため、必ずしも機能するとは限りません。通常、0xFFF...FFFF (マイナス 1、またはすべて 1) が true として使用されますが、標準に依存することはできません。
さて、あなたが何とかの値を完全に制御していて、それを厳密に false の場合は 0 に、true の場合は 1 に保つ場合、あなたが求めていたことを行うことができます:
number += 何とか <<n;
また、分岐、余分なキャッシュ ライン フィルなどの可能性を回避します。
ただし、一般的なケースに戻り、次の一般的なソリューションを採用します。
unsigned int fun ( int blah, unsigned int n, unsigned int number )
{
if(何とか) 数 += (1<<n);
戻り値 (数値);
}
そして、最も一般的/使用されている 2 つのプラットフォーム用にコンパイルします。
testl %edi, %edi
movl %edx, %eax
ジェ.L2
移動 $1、%edx
movl %esi, %ecx
%cl、%edx を販売
addl %edx, %eax
.L2:
上記は条件分岐を使用しています。
以下は条件付き実行を使用し、分岐もパイプライン フラッシュも決定論的ではありません。
cmp r0,#0
ムーヴネr3,#1
addne r2、r2、r3、asl r1
移動r0、r2
bx lr
関数呼び出しで引数を再配置することで mov r0,r2 命令を保存できたかもしれませんが、それは学術的なことであり、通常はこれで関数呼び出しを焼き付けることはありません。
編集:
提案どおり:
unsigned int fun ( int blah, unsigned int n, unsigned int number )
{
数値 += ((何とか!=0)&1)<<n;
戻り値 (数値);
}
サブ r0、r0、#0
移動 r0、#1
r0、r2、r0、asl r1 を追加
bx lr
確かに安価で、コードは見栄えがしますが、blah!=0 の結果 (ゼロまたはコンパイラーが true と定義したもの) には常に lsbit が設定されているとは思いません。コンパイラが動作するコードを生成するためにそのビットを設定する必要はありません。おそらく、標準が true の特定の値を指示しているのでしょう。関数パラメーターを再配置することにより、 if(blah) number +=... も3つの単一クロック命令になり、仮定はありません。
EDIT2:
C99標準であると私が理解しているものを見ると:
== (等しい) および != (等しくない) 演算子は、優先順位が低いことを除いて関係演算子に似ています。各演算子は、指定されたリレーションが true の場合は 1 を返し、false の場合は 0 を返します。
これは、上記の編集が機能する理由と、他の乱数ではなく movne r0,#1 を取得する理由を説明しています。
投稿者は C に関して質問をしていましたが、ADA が現在の言語であることにも言及しました。言語に依存しない観点から、上記の C 機能のような「機能」を想定して、if(blah) 数値 = 数値 + (1 <<n)。しかし、これはCタグで尋ねられたので、一般的に(プロセッサに依存しない)Cの最速の結果は、 number += (blah!=0)<<n; だと思います。したがって、Steven Wright のコメントは正しかったので、彼の功績は認められるべきです。
ポスターの仮定も基本的に正しいです。何とか0または1の形式にできる場合は、分岐がないという意味で数学でそれを使用する方が高速です。ブランチよりもコストがかからずにその形にするのがコツです。