C and C++ Programming

Avoiding Assignment/Equality Bugs

If compairing a variable to a constant, the constant should be the lvalue (on the left).

Fo example, this erroneous code will compile without errors (good compilers will warn you):

while (foo = NULL)
   { ... }

The pointer foo will be set to NULL and the loop will never be entered. On the other hand, trying to build the following will always generate an error:

while (NULL = foo)
   { ... }
test.c: In function `main':
test.c:7: error: invalid lvalue in assignment

Using Bitflags

Bitflags are a method of storing multiple flags, which are not mutucally exclusive, in one variable.

You've probably seen them before in system or library calls. Each flag is a bit position which can be set on or off. You then have a bunch of bitmasks declared with #define for each bit position so you can easily manipulate it:

#define LOG_ERRORS            1  // 2^0, bit 0
#define LOG_WARNINGS          2  // 2^1, bit 1
#define LOG_NOTICES           4  // 2^2, bit 2
#define LOG_INCOMING          8  // 2^3, bit 3
#define LOG_OUTGOING         16  // 2^4, bit 4
#define LOG_LOOPBACK         32  // and so on...

unsigned flags;

// WARNING: assigning a value will clobber any other flags, so you
// should generally only use the = operator when initialising vars.

// initialising the flags
flags = LOG_ERRORS;  // sets to 1 i.e. bit 0

//initialising to multiple values with OR (|)
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3

// setting one flag on, leaving the rest untouched
// OR bitmask with the current value
flags |= LOG_INCOMING;

// testing for a flag
// AND with the bitmask before testing with ==
if ((flags & LOG_WARNINGS) == LOG_WARNINGS)
   ...

// testing for multiple flags
// as above, OR the bitmasks
if ((flags & (LOG_INCOMING | LOG_OUTGOING))
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

// removing a flag, leaving the rest untouched
// AND with the inverse (NOT) of the bitmask
flags &= ~LOG_OUTGOING;

// toggling a flag, leaving the rest untouched
flags ^= LOG_LOOPBACK;

A variable that's really a function

Stolen from the FreeBSD errno manpage:

extern int * __error();
#define errno (* __error())

ANSI codes and colours

Before you start, make sure you're checking terminal types or at least providing a monochrome option so people who use terms that don't support this don't suffer excape characters all over their text.

The codes themselves have a starting sequence, (Escape-[ or \033[) then a set of numbers seperated by semicolons which may contain a text attribute normal, bold, underlined, blinking...) and foreground and background colours. The code is closed with an m.

Basic ANSI Properties:

Enable       Disable          Foreground     Background

0 normal                      30 black       40 black
1 bold       22 unbold        31 red         41 red
4 underline  24 ununderline   32 green       42 green
5 blink      25 unblink       33 yellow      43 yellow
7 inverse    27 uninverse     34 blue        44 blue
9 strike     29 unstrike      35 magenta     45 magent
                              36 cyan        46 cyan
                              37 white       47 white
                              39 default     49 default

Attributes are not as widely supported as simple colours. Often in an X environment the user has chosen a bold font and bold will have no effect; underlined, blinking and inverse text sometimes fail for no particular reason. The codes for cancelling an attribute (unbold etc) sometimes do something completely different. Strikethrough is "standard" but I've never seen it actually work.

For these reasons you're probably better off just sticking with the colours. A C example follows:

#define ANSI_NORMAL  "\033[0m"

/* these are all normal text with black background (40) */
#define ANSI_RED     "\033[0;31;40m"
#define ANSI_GREEN   "\033[0;32;40m"
#define ANSI_YELLOW  "\033[0;33;40m"
#define ANSI_BLUE    "\033[0;34;40m"
#define ANSI_MAGENTA "\033[0;35;40m"
#define ANSI_CYAN    "\033[0;36;40m"
#define ANSI_WHITE   "\033[0;37;40m"

#define ANSI_BOLD_RED      "\033[1;31;40m"
#define ANSI_UNDERLINE_RED "\033[4;31;40m"
#define ANSI_BLINK_RED     "\033[5;31;40m"


printf("%sI am blue!%s\n", ANSI_BLUE, ANSI_NORMAL);

Always, always close the text with the 033[0m code (normal text) or else the text after your program ends will be affected...

Polymorphic Structures in C

This can be achieved with a little creative union and struct work. The basic idea is to have a structure representing a superclass, which contains a union of all the other subclasses.

You will need another entity (preferably an enumeration) in the superclass and all subclasses to determine what type of struct it is.

Example:

typedef struct{
   int type;
   float ypos;
   float xpos;
   float length;
   float height;
} Shape_Triangle

typedef struct{
   int type;
   float ypos;
   float xpos;
   float length;
} Shape_Square

typedef struct{
   int type;
   float ypos;
   float xpos;
   float radius;
} Shape_Circle

typedef union{
  int type;
  Shape_Square square;
  Shape_Triangle triangle;
  Shape_Circle circle;
} Shape;

...

Shape s = getShape();
switch(s.type)
{
   case SHAPE_SQUARE:
      s.Shape_Square.length=3;
      break;
   case SHAPE_TRIANGLE:
      s.Shape_Triangle.height=4;
      break;
   case SHAPE_CIRCLE:
      s.Shape_Circle.radius=5;
      break;
}

A drawback of this method is that you need to duplicate the members in the substructure, and you must make sure the type variables are all in the same physical position (first is best) in the struct/union. Alternatively, use a struct for the superclass and subclass:

typedef struct{
   float length;
   float height;
} Shape_Triangle

typedef struct{
   float length;
} Shape_Square

typedef struct{
   float radius;
} Shape_Circle

typedef union{
  Shape_Square square;
  Shape_Triangle triangle;
  Shape_Circle circle;
} Shape_Union;

typedef struct{
   int type;
   float xpos;
   float ypos;
   Shape_Union subshape;
}

...

Shape s = getShape();
switch(s.type)
{
   case SHAPE_SQUARE:
      s.subshape.Shape_Square.length=3;
      break;
   case SHAPE_TRIANGLE:
      s.subshape.Shape_Triangle.height=4;
      break;
   case SHAPE_CIRCLE:
      s.subshape.Shape_Circle.radius=5;
      break;
}

This approach requires extra typing "through" the union.