Search code examples
clinuxbit-manipulationboolean-operations

Confusion with bitwise operations &


The following line should be testing whether the current file is a directory or not:

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

where stbuf is of type

 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 */
 };

and S_IFMT and S_IFDIR are defined as

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

I can't understand how the statement given above will work? Please can anyone explain logic behind it.
Thanks.


Solution

  • For each pair of corresponding bits from the source and the mask, the logical AND operation gives an on bit (1) if and only if both bits were set to 1. This means all bits not turned on in the mask are zeroed. Suppose you have a single byte with bits abcdefgh where each of the letters is a bit, so either 0 or 1. If you have a mask whose value is e.g. 00111000, AND-ing the two will result in 00cde000. Thus, using the mask, you "cut out" just a substring of the bits. Often, the mask has only one bit set, in which case you will be testing a single bit. In your example, the mask is S_IFMT. Now you can take a number of values encooded in the space of the 3 bits the mask leaves untouched, like 00101000, 00011000 or anything that has all its 1 bits inside the space separated by the mask (this is what your S_IFDIR is in your example), and you can compare against the. So, if plain words the whole operations means "take a substring of the bits of a variable and check if it is one of the predefined values". This all is done for space effciency, if it were not important, the designers would probably have defined a separate variable for the mode field.