与按位运算混淆&

时间:2012-06-20 16:17:02

标签: c linux bit-manipulation boolean-operations

以下行应该测试当前文件是否是目录:

if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
      //file is a directory.

其中stbuf的类型为

 struct stat            /* inode information returned by stat */
 {
      dev_t st_dev;     /* device of inode */
      ino_t st_ino;     /* inode number */
      short st_mode;    /* mode bits */
      short st_nlink;   /* number of links to file */
      short st_uid;     /* owners user id */
      short st_gid;     /* owners group id */
      dev_t st_rdev;    /* for special files */
      off_t st_size;    /* file size in characters */
      time_t st_atime;  /* time last accessed */
      time_t st_mtime;  /* time last modified */
      time_t st_ctime;  /* time originally created */
 };

S_IFMTS_IFDIR定义为

#define S_IFMT 0160000  /* type of file: */
#define S_IFDIR 0040000 /* directory */

我无法理解上面给出的陈述是如何起作用的?任何人都可以解释它背后的逻辑 感谢。

3 个答案:

答案 0 :(得分:3)

它基本上表示如果你取出stbuf.st_mode的所有位并将它们排列在上面 S_IFMT中的位。您将生成第三行,即AND操作的结果。对于AND操作,请参阅以下truth table,如果两个输入均为1,则输出仅为1

input1| input2| output
------+-------+-------
  0   |   0   |   0
  0   |   1   |   0
  1   |   0   |   0
  1   |   1   |   1

对于每个相应的位位置,将0置于数字下方,除非 指定位置中相应位的为{{1在这种情况下,您可以录制1

也许这个视觉形象会有所帮助:

1

将此结果位模式与st_mode | 0100 0000 0000 0000 0000 0000 0000 0000 S_IFMT | 1110 0000 0000 0000 0000 0000 0000 0000 bitwise & |=========================================== result | 0100 0000 0000 0000 0000 0000 0000 0000 的位模式进行比较。如果它们相等,你就有了一个目录。

也许这个问题Using Struct Stat()也会有所帮助。最后,除了此结构的所有血腥细节之外,stat(3) man page还有一些示例代码。

答案 1 :(得分:2)

按位AND获取与特定设置S_IFDIR有关的位。

如果结果为S_IFDIR,则设置该标志。 0160000以八进制表示,表示整数的前3位。 0040000是第二位,所以它们重叠。

答案 2 :(得分:2)

对于来自源和掩码的每对相应位,当且仅当两个位都设置为1时,逻辑AND操作给出一个on位(1)。这意味着掩码中未打开的所有位都归零。假设你有一个字节,其中的位为abcdefgh,其中每个字母都是一位,所以要么为0或1.如果你有一个掩码,其值为例如0或1。 00111000,AND这两个将导致00cde000。因此,使用掩码,您只能“切出”位的子串。通常,掩码只有一个位设置,在这种情况下,您将测试一个位。在您的示例中,掩码是S_IFMT。现在,您可以在掩码不受影响的3位空间中进行多个值编码,例如00101000,00011000或在掩码分隔的空间内具有所有1位的任何值(这是您的示例中的S_IFDIR) ),你可以比较。因此,如果简单的话,整个操作意味着“获取变量位的子串并检查它是否是预定义值之一”。这一切都是为了节省空间,如果不重要,设计师可能会为模式字段定义一个单独的变量。