Recommended

2009-03-26

The naïve way of defining a C macro which tests whether a character is a digit (assuming an ASCII-based character set) is #define ISDIGIT(c) ((c) >= '0' && (c) <= '9'). There is a fundamental problem with this naïve definition: it evaluates its argument c more than once, so for example ISDIGIT(x++) will increment x by 2 in some cases. The question naturally arises if there is a macro definition #define ISDIGIT(c) ..., which uses c exactly once. Indeed, there is:#define ISDIGIT(c) ((c) - '0' + 0U <= 9U). The capital Us in the expression enforce unsigned calculation, so if c is less than '0', then (c) - '0' + 0U becomes a large positive number instead of a negative number with small absolute value, so the comparison will (correctly) return false.

The following code contains solutions for ISDIGIT, ISALPHA and ISXDIGIT, the latter not being practical because of the excessive use of arithmetic operations.