CSc 352: C Coding Guidelines

The coding guidelines we will follow are based on GNU coding styles, with some modifications based on personal taste.  Your programs will be expected to follow these guidelines unless explicitly directed otherwise.
 

0. Program Structure

The design of a procedural program is quite different from that of an object-oriented one. A very important aspect of program design is that the code should be written in a way that makes it easy to be read and understood by others. To develop good habits in this regard, we'll follow the following (rather rigid) set of rules:

1. Robustness

2. Error Messages

3. Comments

4. Clean Use of C Constructs

5. Naming Files, Variables and Functions

6. Information Hiding

When you declare a struct or union, you should also define macros to access its fields.  Avoid accessing the fields directly in the main body of the program: instead, use these macros for accessing the fields.  Thus, avoid writing code like this:
struct tn {
  int ntype;
  union {
    int nval;
    char *name;
    struct tn *child[2];
  } flds;
} *tptr;

...

if (tptr->ntype == EXPR_PLUS) {
  emit_code(tptr->flds.tn[0]);
  emit_code(tptr->flds.tn[1]);
}

Instead, write
struct tn {
  int ntype;
  union {
      int nval;
      char *name;
      struct tn *child[2];
  } flds;
} *tptr;

#define Type(x)  ((x)->ntype)
#define Value(x) (((x)->flds).nval)
#define Name(x)  (((x)->flds).name)
#define Child(x,i) (((x)->flds).child[i])

 ...

if (Type(tptr) == EXPR_PLUS) {
  emit_code(Child(tptr,0));
  emit_code(Child(tptr,1));
}

The latter style is easier to understand (e.g., it's easier to see that Child(tptr,0) refers to the 0th child of the node that tptr points to than tptr->flds.tn[0]); and changes in the data structure, e.g., to improve performance, are easier to accommodate and less prone to bugs.


Acknowledgements

The material in this document is based on GNU coding styles.