4

argv is an array of constant pointers to characters

char * const argv[] // 1

argv is an array of pointers to characters, which are constant

const char * argv[] // 2

Is there a tip to remember number 1?

Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208

3 Answers3

5
const char * argv[] // 2

can also be written:

char const * argv[] // 3

because C doesn't care about the order of const in the type. If you write it this way, then the thing actually const is the thing to the left of the keyword const. The form where const is first is the one exception to that rule; but in that case there's nothing to the left of const so it is easy to avoid that case with this rule of thumb.

char*             // mutable pointer to mutable char
char const*       // mutable pointer to constant char
char * const      // constant pointer to mutable char
char const* const // constant pointer to constant char
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 2
    @abc: I can't really take credit for it -- I learned this from [C++ Templates: The Complete Guide](http://www.amazon.com/Templates-The-Complete-Guide-ebook/dp/B003YL3OYG/ref=tmm_kin_title_0?ie=UTF8&qid=1369195044&sr=8-1) – Billy ONeal May 22 '13 at 03:58
  • 1
    Well thanks for the great reference then! – Ankur Agarwal May 22 '13 at 15:06
2
char * const argv[]

There are simple rules, as cskoala mentioned in his answer:

  1. Find identifier

    char * const     argv     []
                      |
                  identifier
                      1  
    
  2. Read all element to the right of identifier, left-to-right

    char * const     argv       []
                      |         |
                  identifier  array
                      1         2
    
  3. Read all element to the left of identifier, right-to-left

    char     *     const    argv       []
      |      |       |        |         |
    char  pointer  const  identifier  array
      5      4       3        1         2
    

Result: (1) argv is (2) an array of (3) constants of type (4) pointer to (5) char


Other examples.

    char  const     *       argv       []
      |     |       |         |         |
    char  const  pointer  identifier  array
      5     4       3         1         2

Result: (1) argv is (2) an array of (3) pointers to (4) constants of type (5) char

    char  const     *     const    argv       []
      |     |       |       |        |         |
    char  const  pointer  const  identifier  array
      6     5       4       3        1         2

Result: (1) argv is (2) an array of (3) constants of type (4) pointer to (5) constant of type (6) char


There is notably ugly exception to this simple rule. For some reason C allows to place const modifier to the left of type, like in your example:

    const  char     *       argv       []
      |      |      |         |         |
    const  char  pointer  identifier  array
      4      5      3         1         2

In my opinion it's better to avoid such declarations, for consistency. It's often leads to confusion or errors.

kotlomoy
  • 1,420
  • 8
  • 14
1

At my university, we're taught something called the "Right-Left Rule" which is pretty much a way to read variables in a way that tells you what they are.

Here's the link to the page: http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html

It looks like a lot but after a few examples, it helps makes sense of a lot of these type of things! =]

corgichu
  • 2,580
  • 3
  • 32
  • 46
  • And nothing about const usage? – kotlomoy May 22 '13 at 00:11
  • @kotlomoy yeah.. I guess the document doesn't say anything about const, but applying the rule to his question will read it exactly as he said he wanted to remember and instead of memorizing the statement, it's just a simple rule that can be applied to other similar statements. Should I try to specify more for the const example? – corgichu May 22 '13 at 00:15
  • @kotlomoy `const` does not violate the right-left rule. `const int*` is a pointer to an integer constant. What is the problem? – jamesdlin May 22 '13 at 00:54
  • @jamesdlin problem is that `int const *` is not a pointer constant. – kotlomoy May 22 '13 at 01:00
  • @kotlomoy All the more reason to avoid `int const*` and to prefer `const int*`. – jamesdlin May 22 '13 at 01:03
  • @jamesdlin Problem is that there is no consistency. Without consistent rule programmer must remember when const can be to the left of type and when to the right. It was hard for me when I started to use const modifiers, it's hard for many newby programmers. – kotlomoy May 22 '13 at 01:15
  • @kotlomoy There's plenty of consistency. You almost always can just follow the right-to-left rule. `const T*` works fine when read from right-to-left and is unambiguous. Furthermore, K&R, Stroustrup, the ISO C and ISO C++ standards all use `const T*`/`const T&`, so it has plenty of inertia. Also see http://stackoverflow.com/questions/3694630/c-const-reference-before-vs-after-type-specifier/3695979#3695979 – jamesdlin May 22 '13 at 01:31
  • @jamesdlin Consistency is not readability (even though I'm sure "pointer to double constant" is less readable than "pointer to constant of type double"). Everywhere else `const` is a suffix. That is consistency. – kotlomoy May 22 '13 at 07:19