逻辑运算符 位运算符
让我们剖析一个奇怪的位标记程序,它花了我一秒钟的时间来理解。 这样,我们有望对位掩码和按位或逻辑如何有效地操纵值有更深入的了解。
具体来说,我们要看的程序将打印open()函数(包含在< fcntl.h
>库中)使用的不同访问模式标志的二进制表示形式。 访问模式标志用于指定要打开或创建的文件的权限。 这些标志具有“对应于单个位的值”( Hacking:The Art of Exploitation, Jon Erickson),因此,可以将这些标志添加在一起(使用OR运算符)以创建新行为。 让我们看一下以下程序:
![](https://i-blog.csdnimg.cn/blog_migrate/4d551ac85bbfa38881ccff9c54a39574.png)
![](https://i-blog.csdnimg.cn/blog_migrate/90e87a9c4ef0f4a6e32de1ef4226b294.png)
![](https://i-blog.csdnimg.cn/blog_migrate/caa787e86d99b2eff2dd137db3f2c6bb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/366620859a9f11082a20292b555297fb.png)
我第一次看到该程序时,我不知道它在做什么,所以让我们逐步了解一下。 首先, main()函数将访问模式标志的值发送到display_flags()函数。
display_flags函数显示访问模式标志的字符串和十进制值。 Display_flags()然后发送接入模式标志的到binary_print十进制值()。
Binary_print()具有内部和外部循环结构。 我们使用值为4278190080的位掩码(“掩码”变量)(此数字需要四个字节)。 用二进制表示,此掩码看起来像八个1,然后是24个零:
11111111000000000000000000000000
然后,我们得到一个变量“ shift”,其值为16777216 ,看起来像是一个1,后跟二进制的24个零:
1000000000000000000000000
外循环运行四次,并负责隔离每个字节。 外循环内的第一行代码:
byte = (value & mask) /shift;
对访问模式标志的值和掩码的值进行按位与运算。 然后,将所得运算的乘积除以移位,以便仅保存最左边的八个位。 这是一个例子:
value = 10000000000
mask = 1111111100000000
shift = 100000000
value
& mask
______________ = 10000000000 / shift = 00000100
在这种情况下,字节变量将保持值为4 。
隔离完每个字节后,我们转到内部循环。 内部循环迭代字节中的每个位,并检查是否已设置msb(最高有效位(最左位))。 如果是,我们将打印“ 1”。 如果不是,我们打印一个“ 0”,在打印完该位后,我们通过将字节乘以2向左移动字节(得到一个新的msb):
byte *=2
Ex. Four becomes eight:
A = 00000100
A *= 2
A = 00001000
在内部循环之后,我们将掩码和移位变量都除以8,以便将位向右移动八位。 我们这样做是为了检查值中的低位是否已设置。 我们重复此过程:隔离下一个字节,检查msb是否已设置,然后将这些位左移,以便我们可以检查下一个msb中的四个字节。
在此过程结束时,我们将获得访问模式标志的完整二进制表示形式。 尽管它本身并不是很有用,但是对于进一步的低级编程工作来说,拥有可以快速生成所要查看内容的二进制表示的功能可能会有所帮助。 如果没有其他要求,那么最好对位在程序中的移动方式有一个扎实的了解,因为它可能使您思考优化代码的时间和空间复杂度的方法。
在结束之前,我想演示如何将OR
按位运算符用作加法运算符。 O_WRONLY
标志的值为1 , O_APPEND
标志的值为1024 , O_CREAT
标志的值为64 。 当我们调用display_flags()并打印O_WRONLY
|的十进制表示形式时。 O_APPEND
| O_CREAT
,我们得到1089 (与将它们加在一起一样)。 只要每个数字中的所有位都是唯一的,这将始终有效。
![](https://i-blog.csdnimg.cn/blog_migrate/0fce5323fc6ee4edfa3ad58e527f1734.png)
翻译自: https://hackernoon.com/change-your-codes-behavior-by-using-bitwise-operators-d1ll378m
逻辑运算符 位运算符