Thursday, September 27, 2012

const char * const * ptr

Today I was tasked to Lint an imported module. Things went all for the most part, typical Linting affair: resolving unreferenced variables, uninitialized variables, potentially unbounded string copy, etc. Then I came across this gem: 

Info 818: Pointer parameter 'var' (line 123) could be declared as pointing to const

Looking at the log, I figured all I was missing was a const qualifier. Not that bad. 
Looking at the code, the offending line looked like this:

const char **values

which looks..... correct. 
I proceed onto consulting Google for the next 2 hours while scratching my head. Eventually I reviewed the C const usage: 

const char *ptr; // ptr is volatile, content of ptr is const
char * const ptr; // ptr is const, content of ptr volatile 
const char * const ptr; // ptr is const, content of ptr is also const

Looking at the code closely, **values represents a table of strings, thus: 

*table = table[0]; // pointer to the first string in the table
**table = table[0][0]; // points to the first byte of the first string in the table

The function in question performs string comparison by iterating through all strings in the table via: 

tables++; // go to the next string

But since pointer to the strings are not modified (ie. *table or table[i]), Lint was effectively complaining that the API could be further qualified as: 

const char * const * values // because *table is never modified

I then went a bit further and tried: 

const char * const * const values // let's also make table itself const

and confirmed that the following line now generates an error: 

table++; // this is now illegal

But since the function was defined as a callback to hook into another 3rd party library, I was unable to make the change as Lint suggested and had to purposely violate the const requirement to silence Lint: 


*table = *table; // Lint now thinks *table has been updated. 

But hey, I learnt something interesting today!