views:

153

answers:

4

Hi,

I am trying to understand array declarations, constness, and their resulting variable types.

The following is allowed (by my compiler):

      char s01[] = "abc" ;  // typeof(s01) = char*
const char s02[] = "abc" ;  // typeof(s02) = const char* (== char const*)
char const s03[] = "abc" ;  // typeof(s03) = char const* (== const char*)

Alternatively, we can declare the array size manually:

      char s04[4] = "abc" ;  // typeof(s04) = char*
const char s05[4] = "abc" ;  // typeof(s05) = const char* (== char const*)
char const s06[4] = "abc" ;  // typeof(s06) = char const* (== const char*)

How do I get a resulting variable of type const char* const? The following are not allowed (by my compiler):

const char s07 const[] = "abc" ;
char const s08 const[] = "abc" ;
const char s09[] const = "abc" ;
char const s10[] const = "abc" ;
const char s11 const[4] = "abc" ;
char const s12 const[4] = "abc" ;
const char s13[4] const = "abc" ;
char const s14[4] const = "abc" ;

Thanks

+5  A: 
const char *const s15 = "abc";
ruibm
It is helpful to read from right-to-left to understand what is constant. E.g. `char *const s15` means constant-pointer-to-char. `char const *s15` means pointer-to-constant-char. `char const *const s15` means constant-pointer-to-constant-char. Try it! Right-to-left!
PP
@PP: The right-to-left rule doesn't apply in all circumstances, though. e.g. `int blah[5][2]`. The best summary of how to read declarators I've ever found is here: http://msdn.microsoft.com/en-us/library/1x82y1z4.aspx.
Oli Charlesworth
@PP: It's not right-to-left any more than it's left-to-right, it's **inside-out**.
Gilles
This is the answer I was seeking. I was stuck on the idea that [] allocates on the stack (when declared in a function). If it is a constant pointer to an array of constant chars, I don't need to allocate on the stack. One time in program data space is OK. Who knows where "abc" is allocated here, and who cares. We use `s15` as an absolute constant. We cannot reassign the pointer `s15` nor can we change the value(s) to which it points (`"abc"`).Thanks!
KCArpe
+3  A: 

s01 et al are not really pointer types, they're array types. In that sense, they already act a bit like const pointers (you cannot re-assign s01 to point somewhere else, for instance).

Oli Charlesworth
+1  A: 

Use cdecl:

cdecl> declare foo as constant pointer to array of constant char
Warning: Unsupported in C -- 'Pointer to array of unspecified dimension'
        (maybe you mean "pointer to object")
const char (* const foo)[]
cdecl> declare foo as constant pointer to array 4 of constant char
const char (* const foo)[3]
cdecl> declare foo as constant pointer to constant char
const char * const foo

Pointers to arrays are rarely used in C; usually API functions expect a pointer to the first element.

Gilles
+3  A: 

Your first typeof comments aren't really correct. The type of s01 is char [4], and the types of s02 and s03 are const char [4]. When used in an expression and not the subject of either the & or sizeof operators, they will evaluate to rvalues of type char * and const char * respectively, pointing at the first element of the array.

You can't declare them in such a way that they decay to an rvalue that itself is const-qualified; it doesn't really make any sense to have a const-qualified rvalue, since rvalues can't be assigned to. It's like saying you want a 5 constant that is of type const int rather than int.

caf