tags:

views:

949

answers:

8

If I declare a variable const char ** stringTable, how should I be able to put values to it if it is a const? (It has to be const because a function I am supposed to use takes const char ** as a parameter.)

Edit: No you cannot convert from char ** to const char ** implicitly. Compiler complains: cannot convert parameter 3 from 'char **' to 'const char **'

+4  A: 

That const declaration is a quarantee of the function, you dont have to fullfill it. That means the function will keep your array untouched (it will just read). So you can pass a nonconst variable to a function expecting const.

flolo
You can pass a `char*` to a function expecting `const char*`. You cannot pass `char**` as a `const char**`. Not that it's much of a problem, the implicit cast only works one level deep for simplicity.
Potatoswatter
+3  A: 

You can pass a char ** to a function declared as taking a const char ** -- Might be worth taking a look at the documentation for const on MSDN

Rowland Shaw
+1  A: 

char ** can be converted to const char **, so if you want to call a function which takes a const char ** as a parameter, just supply your char ** and it'll be implicitly converted.

If you want to write a function which takes a const char ** as parameter and then modifies the char data it references, you're breaking the contract with your compiler, even if you might get it to work via casts!

Christoph
You can change the pointer, just not the data it points too. eg: const char **c; const char *str = "my string"; c = //legal
Fire Lancer
Additionaly its legal to change the pointer the const char ** points to ie: *c = str//legal
Fire Lancer
+3  A: 

Apart from other mentions that you can pass char** into function that takes const char **,

const char** is a non-const pointer to const char*, you can declare it and freely put values of type const char* in it.

On the other hand, you would not be able to do it, if you declared it as const char * const * or const char * const * const.

yourfunc(const char **p);
...
const char *array_str[10];
array_str[0] = "foo"; /* OK, literal is a const char[] */
yourfunc(array_str);

Here is what cdecl says:

cdecl> explain const char **table
declare table as pointer to pointer to const char
cdecl> explain const char * const *table
declare table as pointer to const pointer to const char
cdecl> explain const char * const * const table
declare table as const pointer to const pointer to const char
Alex B
A: 

With my compiler (gcc version 3.4.4 in cygwin), I found that I could pass char * to const char *, but not char ** to const char **, unlike what most of the answers are saying.

Here is one way you can build something up that works; maybe it will help you.

void printstring( const char **s ) {
  printf( "%s\n", *s );
}

int main( int argc, char** argv ) {

  char *x = "foo";  // here you have a regular mutable string

  const char *x2 = x;  // you can convert that to a constant string

  const char **y = &x2;  // you can assign the address of the const char *

  printstring(y);


}
Dave Costa
`char *x = "foo"` shouldn't compile because "foo" is `const char*`. There's no need for `x2` because you can assign a `char*` into a `const char**` array.
Potatoswatter
A: 

you can un-const char* by using a cast operator: (char*)

void do_something(const char* s)
{
char* p=(char*)s;
p[0]='A';
}

use the same idea with the arrays char**

Pierre
A: 

Wow, I'm surprised nobody got this! Maybe I can get a necromancer badge. Implicit const casting only scans one level deep. So a char* can become a const char* but it won't dig deep enough inside the a char** type to find what needs to be changed to make it a const char**.

#include <iostream>
using namespace std;

void print3( const char **three ) {
        for ( int x = 0; x < 3; ++ x ) {
                cerr << three[x];
        }
}

int main() {
         // "three" holds pointers to chars that can't be changed
        const char **three = (const char**) malloc( sizeof( char** ) * 3 );
        char a[5], b[5], c[5]; // strings on the stack can be changed
        strcpy( a, "abc" ); // copy const string into non-const string
        strcpy( b, "def" );
        strcpy( c, "efg" );
        three[0] = a; // ok: we won't change a through three
        three[1] = b; // and the (char*) to (const char*) conversion
        three[2] = c; // is just one level deep
        print3( three ); // print3 gets the type it wants
        cerr << endl;
        return 0;
}
Potatoswatter
A: 

const char ** indicates that the underlying character is constant. So, while you can't do something like this:

const char **foo = ...;
**foo = 'a';   // not legal

but there is nothing preventing you from manipulating the pointer itself:

// all the following is legal
const char **foo = 0;

foo = (const char **)calloc(10, sizeof(const char *));

foo[0] = strdup("foo");
foo[1] = strdup("baz");

That said, if you did want to modify the actual character data, you could use a non-const pointer and cast it:

char **foo = ...;
func((const char **)foo);
R Samuel Klatchko