Easy rule to read complicated const declarations? Easy rule to read complicated const declarations? c c

Easy rule to read complicated const declarations?


The const modifier is trivial: it modifies what precedes it, unlessnothing precedes it. So:

char const* buffer;  // const modifies charchar* const buffer;  // const modifies *

, etc. Generally, It's best to avoid the forms where nothing precedesthe const, but in practice, you're going to see them, so you have toremember that when no type precedes the const, you have to logicallymove it behind the first type. So:

const char** buffer;

is in fact:

char const** buffer;

, i.e. pointer to pointer to const char.

Finally, in a function declaration, a [] after reads as a * before.(Again, it's probably better to avoid this misleading notation, butyou're going to see it, so you have to deal with it.) So:

char * const argv[],  //  As function argument

is:

char *const * argv,

a pointer to a const pointer to a char.


(Trying to focus on other aspects of the question)

The rule of thumb for const declarations is to read them from right to left and const modifies the next token. Exception: At the beginning of a declaration const modifies the previous token.

There is a rationale behind this exception - for elementary declarations const char c looks for some people more natural than char const c - and it is reported that a precursor form of const char c predates the final const rule.

getopt

int getopt(int argc, char * const argv[], const char *optstring);

or

int getopt(int argc, char * const * argv, const char *optstring);

Which means that argv is a pointer to const vector of pointers to non-const strings.

But one would expect following declaration:

int getopt(int argc, char const * const * argv, const char *optstring);

(pointer to const vector to const strings)

Because getopt() is not supposed to change the strings referenced via argv.

At least char ** (as used in main()) automatically converts to char * const * argv.

Clang

ASTUnit::LoadFromCommandLine(...,  const char **argv, ...);

Which means that argv is a pointer to a non-const array of pointers to const strings.

Again one would expect const char * const *argv for the same reason as above.

But this is more noticeable because char ** does not convert to const char **, e.g.

int main(int argc, char **argv) {  const char **x = argv; // Compile error!  return 0;}

yields a compile error, where

int main(int argc, char **argv) {  char * const *x = argv;  return 0;}

and

int main(int argc, char **argv) {  const char * const *x = argv;  return 0;}

do not.