[英]How to toggle a bit n times without using loop in C/C++?
我想切換n次而不循環。
像在切換3次之后的1(bit)將為0,依此類推。 為了切換1次,我使用bit ^ = 1。 我實際上搜索了一些操作公式來做到這一點。
如果我理解正確,則需要切換N
次。
現在,將垃圾箱切換N次等於翻轉N%2次,因此:
b ^= (N%2);
Modulo 2與N&1
相同,因此您還可以編寫:
b ^= (N&1);
廣義解:
int toggle_bit_in_word(int word, int bit, int ntimes)
{
auto archetype = ntimes & 1;
auto toggler = archetype << bit;
return word ^= toggler;
}
gcc 5.3產生以下代碼:
toggle_bit_in_word(int, int, int):
and edx, 1
shlx edx, edx, esi
mov eax, edx
xor eax, edi
ret
為了好玩,讓我們以一種幼稚的方式來編寫它並享受歡樂:
int toggle_bit_in_word_naiive(int word, int bit, int ntimes)
{
auto toggler = 1 << bit;
while (ntimes--)
word ^= toggler;
return word;
}
輸出(5.3):
toggle_bit_in_word_naiive(int, int, int):
mov ecx, 1
mov eax, edi
shlx esi, ecx, esi
lea edi, [rdx-1]
test edx, edx
je .L48
lea ecx, [rdx-8]
shr ecx, 3
add ecx, 1
lea r9d, [0+rcx*8]
cmp edi, 12
jbe .L4
vmovd xmm1, esi
xor r8d, r8d
vpxor xmm0, xmm0, xmm0
vpbroadcastd ymm1, xmm1
.L5:
add r8d, 1
vpxor ymm0, ymm0, ymm1
cmp ecx, r8d
ja .L5
vpxor xmm1, xmm1, xmm1
vperm2i128 ymm2, ymm0, ymm1, 33
vpxor ymm0, ymm0, ymm2
sub edi, r9d
vperm2i128 ymm2, ymm0, ymm1, 33
vpalignr ymm2, ymm2, ymm0, 8
vpxor ymm0, ymm0, ymm2
vperm2i128 ymm1, ymm0, ymm1, 33
vpalignr ymm1, ymm1, ymm0, 4
vpxor ymm0, ymm0, ymm1
vmovd ecx, xmm0
xor eax, ecx
cmp edx, r9d
je .L47
vzeroupper
.L4:
xor eax, esi
test edi, edi
je .L48
xor eax, esi
cmp edi, 1
je .L48
xor eax, esi
cmp edi, 2
je .L48
xor eax, esi
cmp edi, 3
je .L48
xor eax, esi
cmp edi, 4
je .L48
xor eax, esi
cmp edi, 5
je .L48
xor eax, esi
cmp edi, 6
je .L48
xor eax, esi
cmp edi, 7
je .L48
xor eax, esi
cmp edi, 8
je .L48
xor eax, esi
cmp edi, 9
je .L48
xor eax, esi
cmp edi, 10
je .L48
xor eax, esi
xor esi, eax
cmp edi, 11
cmovne eax, esi
ret
.L47:
vzeroupper
.L48:
ret
8 /
當然,當優化器擁有所需的所有信息時,即使是純朴的代碼也會變得高效:
int main(int argc, char**argv)
{
return toggle_bit_in_word_naiive(argc, 3, 3);
}
結果:
main:
mov eax, edi
xor eax, 8
ret
如果您僅獨立地操作位,則這是不可能的。
那是因為特定的位不知道其前兩個狀態。
如果要一個周期為4的周期,則至少需要2位。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.