在C中交换整数中的位,你能给我解释一下这个函数吗?
我想写一个函数,它接收一个在C中交换整数中的位,你能给我解释一下这个函数吗?,c,bit-manipulation,bitwise-operators,swap,bitwise-xor,C,Bit Manipulation,Bitwise Operators,Swap,Bitwise Xor,我想写一个函数,它接收一个无符号字符,在第2位和第4位之间交换,并返回新的数字 我不允许使用if语句 unsigned char SwapBits(unsigned char num) { // preserve only bit 2 unsigned char bit2 = num & 0x04; // preserve only bit 4 unsigned char bit4 = num & 0x10; // mo
无符号字符
,在第2位
和第4位
之间交换,并返回新的数字
我不允许使用if
语句
unsigned char SwapBits(unsigned char num)
{
// preserve only bit 2
unsigned char bit2 = num & 0x04;
// preserve only bit 4
unsigned char bit4 = num & 0x10;
// move bit 2 left to bit 4 position
unsigned char bit2_moved = bit2 << 2;
// move bit 4 right to bit 2 position
unsigned char bit4_moved = bit4 >> 2;
// put the two moved bits together into one swapped value
unsigned char swapped_bits = bit2_moved | bit4_moved;
// clear bits 2 and 4 from the original value
unsigned char num_with_swapped_bits_cleared = num & ~0x14;
// put swapped bits back into the original value to complete the swap
return num_with_swapped_bits_cleared | swapped_bits;
}
所以我找到了这个函数,在其他函数中,但这是最简单的一个
所有其他函数都涉及异或,老实说,我并不真正理解
unsigned char SwapBits(unsigned char num)
{
unsigned char mask2 = ( num & 0x04 ) << 2;
unsigned char mask4 = ( num & 0x10 ) >> 2;
unsigned char mask = mask3 | mask5 ;
return ( num & 0xeb ) | mask;
}
unsigned char SwapBits(unsigned char num)
{
无符号字符mask2=(num&0x04)>2;
无符号字符掩码=mask3 | mask5;
返回(num&0xeb)|掩码;
}
有人能告诉我这里发生了什么,最重要的是为什么吗?
此处为什么需要AND,为什么需要使用十六进制地址
?
为什么我应该使用0xeb和(255)?我知道这是char的范围,但我为什么要这样做呢
总之,,
我知道怎么读密码。我理解这段代码,但我不理解每一行的目的
谢谢。首先,通常的惯例是从0开始对最低有效位进行编号,然后向上计数。在本例中,您有一个8位的值,因此位从右侧的0到左侧的7
你发布的功能仍然不太正确,但我想我明白你(它)的意图。以下是它正在执行的步骤:
使用遮罩拉出第2位(从右侧第3位)
使用遮罩拉出第4位(从右侧第5位)
将位2向左移动2个位置,使其现在处于位4的原始位置
将第4位向右移动2个位置,使其现在处于第2位的原始位置
将这两个位合并到一个值中,该值现在被第2位和第4位交换
仅从原始值中屏蔽(使用&)位2和4
加入(使用|插入)新交换的位2和4以完成转换
我已经重写了函数,每次显示一个步骤,以帮助使其更清晰。在原始函数或您找到的其他示例中,您将看到许多这些步骤都在同一语句中同时发生
unsigned char SwapBits(unsigned char num)
{
// preserve only bit 2
unsigned char bit2 = num & 0x04;
// preserve only bit 4
unsigned char bit4 = num & 0x10;
// move bit 2 left to bit 4 position
unsigned char bit2_moved = bit2 << 2;
// move bit 4 right to bit 2 position
unsigned char bit4_moved = bit4 >> 2;
// put the two moved bits together into one swapped value
unsigned char swapped_bits = bit2_moved | bit4_moved;
// clear bits 2 and 4 from the original value
unsigned char num_with_swapped_bits_cleared = num & ~0x14;
// put swapped bits back into the original value to complete the swap
return num_with_swapped_bits_cleared | swapped_bits;
}
unsigned char SwapBits(unsigned char num)
{
//只保留第2位
无符号字符位2=num&0x04;
//只保留第4位
无符号字符位4=num&0x10;
//将位2向左移动到位4位置
无符号字符比特2_moved=比特2>2;
//将两个移动的位合并为一个交换值
无符号字符交换位=位2移动位4移动位;
//从原始值中清除位2和4
无符号字符num_,带交换位_cleared=num&~0x14;
//将交换的位放回原始值以完成交换
返回已交换位已清除的num_ |已交换位;
}
倒数第二步num&~0x14
可能需要一些解释。因为我们想保存除第2位和第4位以外的所有原始位,所以我们只屏蔽(擦除)正在更改的位,而不处理其他所有位。我们要擦除的位位于位置2和4,即掩码0x14中的1。所以我们在0x14上做一个补码(~),把它变成所有的1,除了位2和4中的0。然后,我们将这个值与原始数相加,其效果是将第2位和第4位更改为0,而不考虑其他所有位。这使我们能够将新的交换位作为完成该过程的最后一步。您必须阅读
unsigned char SwapBits(unsigned char num)
{
//假设[num]=46,这意味着表示为0b00101110
无符号字符mask2=(num&0x04)>2;
//0b00101110个
//0b00010000 0x10->表示十进制的16或二进制的0b10000或2^4(幂也是位设置后尾随的0的数目)
//0b00…..0 mask4=0,未能同时设置所有位
无符号字符掩码=mask3 | mask5;
//如果mask3[或]mask5设置为:
//0b1001 mask3
//0boo11 mask4
//0b1011掩模
return(num&0xeb)| mask;//您现在知道它是如何工作的了;)解决这个问题。PS:括号之间的操作具有优先级
}
如果您有兴趣学习位运算符的基础知识,可以查看
建立信心后,您可以尝试探索更深层次的按位操作,并查看其对运行时的影响;)
我也推荐阅读,老掉牙的但是好东西
b=((b*0x80200802ULL)&0x0884422110ULL)*0x0101010101ULL>>32;//反转你的字节!
理解第3位和第5位交换的简单函数:
如果要交换位索引3和位索引5,则必须执行以下操作:
int n=0b100010
int mask=0b100000//保留位索引5(从索引0开始)
int mask2=0b1000//保留位索引3
n=(n&mask)>>2 |(n&mask2)>2
//掩码索引5减少2个位置(>>2),并带来位于索引5处的位,由于and操作数,它在n中捕获了该位。
//|(n&mask2)没有地址。十六进制值只是位掩码。在纸上一步一步地计算出来,你会学得更好。@Barmar为什么我们必须>2
和这个>2
看起来很明显。位3和位5相隔两位。你在这里交换他们的位置。然而,0x03
和0x05
确实很奇怪。你确定他们是对的吗?它们不应该是0b10000
(屏蔽第5位)和0b100
(屏蔽第3位)吗?顺便说一句:0xeb不是255,它是235=0b11101011。啊,你请人解释这个函数是如何工作的,但它不工作(你在将原始函数调整到新用途时出错)。也许你应该发布你找到的原始工作代码,并得到解释,然后应用你想要的