3.17 Example 16

  6672 closei (ip, rw)
       int *ip;
       {
         register *rip;
         register dev, maj;
         rip = ip;
         dev = rip->i_addr[0];
         maj = rip->i_addr[0].d major;
         switch (rip->i_mode&IFMT) {

         case IFCHR:
           (*cdevsw[maj].d_close)(dev,rw);
           break;
         
         case IFBLK:
           (*bdevsw[maj].d_close)(dev,rw);
         }
         iput(rip);
       }

This example has a number of interesting features.

The declaration for “d_major” is

    struct {
       char d_minor;
       char d_major;
    }

so that the value assigned to “maj” is the hiqh order byte of the value assigned to “dev”.

In this example, the “switch” statement has onlv two non-null cases, and no “default”. The actions for the recognised cases, e.g.

     (*bdevsw[maj].d_close)(dev,rw);

look formidable

First it should be noted that this is a procedure call, with parameters “dev” and “rw”.

Second “bdevsw” (and “cdevsw”) are arrays of structures, whose “d_close” element is a pointer to a function, i.e.

     bdevsw[maj]

is the name of a structure, and

     bdevsw[maj].d_close

is an element of that structure which happens to be a pointer to a function, so that

     *bdevsw[maj].d_close

is the name of a function. The first pair of parentheses is “syntactical sugar” to put the compiler in the right frame of mind!