And if the macro versions are employed a few times then they would quickly
grow larger than the table anyways.

The table access is not free.  There is overhead in both cases, depending primarily on the complexity of the ctype comparison.

For is isdigit() the comparison is currently just:

   #  define isdigit(c)   ((c) >= '0' && (c) <= '9')

Given c in a register that would boil down to something like the following:

 * compare c to '0'
 * branch if c < '0'
 * compare c to '9'
 * branch if c > '9'

The table look-up version would be something like

   #  define isdigit(c)  ( (table(c) & __DIGIT_MASK) != 0)

Given c in a register that would boil down to something like:

 * get the address of the table
 * offset by (c)
 * AND with __DIGIT_MASK
 * compare with zero
 * branch if zero

So there is no dramatic size savings in that particular case. And the fetch from FLASH is a performance killer too.  Reducing size is not a super strong argument of this change. There would be a substantial reduction in size for some larger more complex ctype functions, however.  Like isalnum():

   #  define islower(c)   ((c) >= 'a' && (c) <= 'z')
   #  define isupper(c)   ((c) >= 'A' && (c) <= 'Z')
   #  define isalpha(c)   (islower(c) || isupper(c))
   #  define isdigit(c) ((c) >= '0' && (c) <= '9')
   #  define isalnum(c)   (isalpha(c) || isdigit(c))

The only pressing argument for change is the fact that the argument is currently re-evaluated numerous times.  That is a problem.

Most released, deeply embedded software  does not do a lot of string processing.  So I could imagine that a motor control system that only has a couple of uses of ctype functions but would pay a pretty big size penalty for using a table.


Reply via email to