What is an array of constant pointers in C?

13,041

Solution 1

No, the const in char *const argv[] is not redundant.

First, const and "constant" are actually two different things in C, even though the const keyword is obviously derived from the word "constant". A constant expression is one that can be evaluated at compile time. const really means "read-only". For example:

const int r = rand();

is perfectly legal.

Yes, the address of an array -- like the address of any object -- is read-only. But that doesn't mean that the value of the array (which consists of the values of its elements) is read-only, any more than any other object is necessarily read-only.

Consider these three declarations:

char *arr1[10];
char *const arr2[10];
const char *arr3[10];

arr1 is a 10-element array of pointers to char. You can modify the char* elements and you can modify the objects that those elements point to.

arr2 is an array of const (read-only) pointers to char. That means that you can't modify the char* elements of the array (once they're initialized) -- but you can still modify the char objects or arrays that those elements point to.

And arr3 is an array of pointers to const char; you can modify the array elements, but you can't modify what they point to.

Now the fact that you used the name argv suggests that you're talking about the second parameter to main, which has some huge effects on this. The language specifies that main's second parameter is

char *argv[]

or, equivalently,

char **argv

There is no const. You can probably get away with adding one, but it's best to follow the form specified by the standard. (Update: I see from your comment that you're asking about the argv parameter of getopt(), which is defined as char * const argv[].)

And since it's a parameter defined as an array, another rule comes into play: a parameter defined as an array of some type is "adjusted" to a pointer to that type. (This rule applies only to parameters.) This isn't a run-time conversion. A function cannot have a parameter of array type.

The relationship between arrays and pointers in C can be confusing -- and there's a lot of misinformation out there. The most important thing to remember is that arrays are not pointers.

Section 6 of the comp.lang.c FAQ is an excellent explanation of the details.

Solution 2

Isn't the address of an array and thus of all its elements as well constant anyway?

Yes, and it is true for any object in C. Recall that by object here, we mean a location in memory having a value and referenced by an identifier. The identifier is bound to a fixed memory location throughout its scope and you cannot change it. You can change the value of the object though.

int a = 4;
a = 6;  // legal. you can change the value of the object
&a = 23456; // illegal. you cannot change the address of the object

Similarly, an array is also an object and each of its elements will have a fixed memory address. However, the value held by an element of the array has nothing to do with the address of the element.

Note that if the declaration appears in a function parameter list, then the following are equivalent

char *const argv[]
char *const *argv

which means that argv is a pointer to an object which is of type char *const, i.e., a constant pointer to a character. It's obvious that char *const *argv and char **argv are different. So let's take another example.

char *const argv[10];

The above statement defines argv to be an array of 10 constant pointers to a character. This means that you have to initialize the array and cannot later change the pointers to point to a different character. However, this has nothing to do with the address of the array elements.

char c = 'A';
char d = 'B';
char *const argv[2] = {&c, &d}; 

argv = &c; // illegal. you cannot the change the address of an object
argv[0] = &d; // illegal. you cannot change the value of the array element
*argv[0] = 'C'; // legal. you change the value pointed to by the element

Without the const qualifier, char *argv[2] means an array of 2 pointers to characters. This is clearly different from the case when we have the const qualifier as explained above. Therefore, to answer your second question, no, the const qualifier is not redundant. That's because the const qualifier qualifies the type of the array elements.

Solution 3

No, it isn't. char *const argv[] is an array of constant pointers to char. So the const makes the pointers in the array constant (you cannot change them to point to other strings in memory).

Share:
13,041
Lavya
Author by

Lavya

Updated on July 28, 2022

Comments

  • Lavya
    Lavya almost 2 years

    Isn't the address of an array and thus of all its elements as well constant anyway?

    And if so, in a declaration like:

    char *const argv[] 
    

    isn't the const qualifier redundant?

  • Eric Lippert
    Eric Lippert about 10 years
    WHere by "read only" you actually mean "write only once", correct?
  • Lavya
    Lavya about 10 years
    @Keith Thompson Thank you for your excellent detailed answer. It not only answered my question and completely cleared the confusion, but also points to some other very cool facts (about the arguments of main being adjusted for example), that I hadn't thought about. (My doubt didn't originate from main() though, it was from the library getopt function: int getopt(int argc, char * const argv[], const char *optstring).) Thank you!
  • Lavya
    Lavya about 10 years
    Thank you for your excellent clarification and valuable additional pointers!
  • Keith Thompson
    Keith Thompson about 10 years
    @EricLippert: By "read only" I mean that the object cannot be modified by referring to its name. A const object can be initialized. You can't modify it by assigning a value to it -- not even once. const int n = 42; is valid; const int n; n = 42; is not.
  • Eric Lippert
    Eric Lippert about 10 years
    @KeithThompson: Thanks for clarifying that.
  • Stav Alfi
    Stav Alfi about 7 years
    @KeithThompson You wrote "And arr3 is an array of pointers" but arr defined as: const char *arr3. Is there a mistake?
  • Keith Thompson
    Keith Thompson about 7 years
    @StavAlfi: There was. I've just fixed it. Thanks for catching that!
  • Stav Alfi
    Stav Alfi about 7 years
    @KeithThompson Thank you, you wrote an excellent explanation!