很久没有玩过C语言的位操作了,今天重温了一下,并做了一道之前自己跟同事聊过的一道题,就是把一个字节按位翻转,举例来说,就是有二进制数(10010011),翻转之后就变为(11001001).
这一道题还是挺容易的,相信学过C语言的人都可以解决出来,简单地说,做一个循环就可以了,但如果想要取得更高的效率,就有很多考究了.
我们先不要看一个字节的情况,因为一个字节实在是太长了点…我们来看看只有两个二进制位的情况下,是怎么样的.
假设有二制数a = 01B,翻转后则为10B,同样的,如果原来是10B,翻转后则为01B.我们再试一下,可以发现如果原来为11B或者00B,翻转后则不变.这时我们可以写出两位二进制数的翻转算法如下:
if( a == 01B || a == 10B )
a ^= 11B;
else
a = a;
大家知道,给某二进制数的某一位异或(^)一个1,可将其取反,所以上面的a ^= 11B实际将a按位取反了,也即是从01B变为10B,或者从10B变为01B,这样我们可以看到他们实现了翻转.
推而广之,翻转一个字节,其实就是把第0位与第7位互换,把第1位与第6位互换等等.那么,上面的式子是否可以推而广之呢?事实上是可以的.
设有a = 10001100B;
执行a ^= 10000001B;
这时,a的二进制数为00001101B,第0位与第7位互换了!推广下去,a ^= 01000010B则是互换第1位和第6位,a ^= 00100100B是第2和第5位等等…….
那,我们实现了这个问题的解法了吗?没有!因为我们刚才没有考虑到当第0位和第7位相等,第1位和第6位相等等等的情况!在两个对应位相等的情况下,根据上面的翻转算法,我们不应该执行异或运算,因此,我们现在的任务就是分辩出对应位是否相等.
大家有没有什么好方法可以分辨出两个位是否相等?
再回头来看给我们很多启示的只有两个位的二进制数a,假设a = 11B,那么,这个数有什么特点呢?我们发现,( a | 11B ) == a 而当a = 01B,10B,00B的时候都不会出现这样的情况.这样我们就识别出11B的特殊情况,那么,还有一种情况就是a = 00B,它又有什么特别呢?仔细想一想,聪明的读者可能已经发现当a = 00B时, ( a ^ 11B ) == ( a | 11B ),而当a = 01B,10B,11B的时候都不会使这个等式成立,这样我们就可以把00B的特殊情况识别出来了.
进行类似上文的从二位二进制推广到八位二进制的方法,把上面的识别算法也推广到八位后,写程序如下:
#include "stdafx.h"
int main(int argc, char* argv[])
{
unsigned char a, b, c;
a = 17;
if( ( b = a | 0x81 ) != a
&& ( c = a^0x81 ) != b )
a = c;
if( ( b = a | 0x42 ) != a
&& ( c = a^0x42 ) != b )
a = c;
if( ( b = a | 0x24 ) !=
&& ( c = a^0x24 ) != b )
a = c;
if( ( b = a | 0x18 ) != a
&& ( c = a^0x18 ) != b )
a = c;
printf("%d\n", a );
return 0;
}
至此,一个将字节按位翻转的程序就出来了,但是,相信好学的读者是不会满足的,还有什么更好地优化它的算法吗?动动脑筋,当然有!
引自:
http://lanphaday.bokee.com/3788582.html
分享到:
相关推荐
这是因为异或操作具有交换律和结合律,当一个位是1,另一个位是0时,异或结果为1,反之为0。所以,对于01B和10B,异或11B(1的位与0的位对应,0的位与1的位对应),相当于全部位翻转。 当扩展到一个字节(8位)时,...
1. **定义字节集变量**:首先,我们需要创建一个字节集变量来存储我们要翻转的数据。例如,`字节集_原始 = ...`,这里省略了具体的数据初始化部分。 2. **获取字节集长度**:使用`取字节集长度`函数来获取字节集的...
总之,"易语言源码易语言字节集翻转源码.rar"是一个宝贵的资源,它提供了用易语言处理二进制数据的实例,对于想要深入理解和使用易语言,尤其是涉及二进制操作的开发者来说,这是一个很好的学习材料。通过研究这个...
例如,你可以创建一个自定义的输入框控件,当用户输入一个数字后,实时显示其按位反转的结果。 总之,基于Qt的整数按位反转实现结合了Qt的数据转换功能和位运算,提供了一种直观且灵活的方式来处理二进制位反转。...
CBC字节翻转攻击与padding oracle攻击 CBC 字节翻转攻击是指在使用 CBC 加密模式时,如果攻击者可以控制明文最后的一部分,并且可以观察到密文的变化,那么攻击者可以通过修改明文的最后一部分来观察密文的变化,...
一个BMP文件通常由文件头、信息头和像素数据三部分组成。文件头包含了文件的基本信息,如文件大小、图像偏移量等;信息头则包含图像的宽高、色彩位深等详细信息;而像素数据则是按照行优先的原则存放的,即从上到下...
高低字节交换(Byte Swapping),又称为字节翻转,是一种处理字节顺序的技术,主要用于解决大端字节序和小端字节序之间的转换问题。大端字节序是指数据的最高有效字节存储在最低地址,而小端字节序则相反,最低有效...
在实际代码中,我们可能会先创建一个字节集,然后通过循环或其他方法将字节集的内容读取出来,反向存储到新的字节集中,最后用新的字节集替换原来的字节集,完成翻转操作。这样的程序逻辑可以确保字节集的顺序得到...
用于TXT文本文档存储的16进制文件的高低字节的转换以及数据校验
5. 完成所有行的处理后,将新内存写入一个新的BMP文件,创建一个水平翻转的图像。 对于垂直翻转,处理方式略有不同,需要从下至上读取像素: 1. 同样,打开BMP文件并获取图像信息。 2. 分配内存。 3. 从最后一行...
- 24位BMP文件每个像素由3个字节表示(红绿蓝各占一个字节)。 3. **Verilog实现图像翻转** - 本例中的代码主要分为两个部分:读取图像数据和写入翻转后的图像数据。 - 使用了`$fopen`和`$fclose`等Verilog内置...
如果一个位是1,另一个位是0,异或结果为1。在按位异或校验和中,我们将所有数据的每一位进行异或操作,最终得到的单一结果就是校验和。 在C#编程语言中,我们可以使用位运算符来实现按位异或校验和。下面是一个...
- 对二进制数据进行按位解析,意味着将二进制数分解为单个位(bit),每个位都有其特定的值和意义,特别是在处理具有特定结构的数据时,如计算机指令、网络报文或硬件寄存器状态。 3. **寄存器字段**: - 寄存器...
比如12345678能变成78563412,如果长度不够,自动补0
首先,我们需要了解`mb_strlen()`函数,它是PHP中的一个多字节安全的字符串长度获取函数。它会根据指定的编码识别字符串中的字符数,而不是字节数。例如: ```php $encoding = 'UTF-8'; $string = '你好,世界!'; ...
在计算机中,字符通常由ASCII或Unicode编码表示,如ASCII码对应一个字节,Unicode码可能需要两个或更多字节。在屏幕上显示字符,我们需要将这些编码转换为像素,这个过程涉及字体渲染技术。 接下来,我们讨论字符的...
在"压缩包子文件的文件名称列表"中提到的"BMPZoom"可能是一个示例程序或者包含示例代码的文件,它演示了如何用二进制方式处理BMP文件并实现翻转和缩放。 总之,理解和操作BMP文件涉及到了计算机图形学的基本概念,...
例如,我们可能有一个结构体,其中包含几个位字段,每个字段代表不同的功能。位域赋值就是向这些位字段赋值的过程,这有助于我们精确控制内存的低级别操作。 ```c struct BitField { unsigned int bit1 : 1; // ...
异或运算常用于判断两个位是否不同,并可以用来翻转一个数值的特定位。例如,如果你想翻转一个数的低4位,可以将它与一个掩码(如00001111)进行异或。 这些位运算符在计算机科学中有着广泛的应用,特别是在处理...