29

In C++, why is it not possible to pass a char** as an argument to a function that accepts const char** , when a conversion from char* to const char* is possible, as shown below

void f1(const char** a)
{

}

void f2(const char* b)
{

}

int main(int argc, char const *argv[])
{
   char* c;

   f1(&c); // doesn't work
   f2(c); //works

   return 0;
}

The compiler output is

test.cpp: In function 'int main(int, const char**)':
test.cpp:15:10: error: invalid conversion from 'char**' to 'const char**' [-fpermissive]
test.cpp:1:6: error:   initializing argument 1 of 'void f1(const char**)' [-fpermissive]
Rakib
  • 7,435
  • 7
  • 29
  • 45
scttrbrn
  • 457
  • 1
  • 4
  • 10

1 Answers1

30

You need to protect contents on both levels of dereference of the pointer. With const char** you could actually modify contents on the 1st dereference.

char *tmp = "foo"; //Deprecated but it's ok for the example
void f1(const char** a)
{
  a[0] = tmp;     //this is legal
  a[0][1] = 'x';  //this is not
}

And this is most probably not intended. It should look like this:

char *tmp = "foo"; //Deprecated but it's ok for the example
void f1(char const* const* a)
{
  a[0] = tmp;    // this is not legal any more
  a[0][1] = 'x'; // this still upsets compiler
}

The compiler does not allow implicit conversion to such "partially" protected pointer types. Allowing such conversion could have nasty consequences as discussed in c++faq pointed out in comment by @zmb. This answer also cites how could you violate constness of an object if this was allowed, using char examples.

One can however implicitly convert to a "fully" protected pointer as shown in the 2nd code example so below code compiles.

void f1(char const* const* a){}
void f2(const char* b){}
int main(int argc, char const *argv[])
{
   char* c;
   f1(&c); // works now too!
   f2(c);  // works
   return 0;
}

Actually there is a bunch of questions and answers on this matter lying around. E.g:

  1. invalid conversion from ‘char**’ to ‘const char**’
  2. Why am I getting an error converting a ‘float**’ to ‘const float**’?

EDIT: I got the 1st example wrong by a bit. Thank for pointing it out!

Community
  • 1
  • 1
luk32
  • 15,812
  • 38
  • 62
  • When you know that there're multiple questions like this one, instead of answering it, flagging it as a dupe is more appropriate, no? – legends2k Aug 16 '13 at 12:59
  • Since it has 6 up-votes maybe it has some original elements that I do not see. I also flagged it. Is it really so bad, that I assumed the other questions are similar but not exactly the same ? Even you said "possible duplicate", not a definite. Actually I took more time writing this comment than answering (sic!) – luk32 Aug 16 '13 at 13:01
  • Of course not that bad, that's why I was not imposing, I was just asking, chill :) Oh and I didn't say `possible duplicate` that is done by SO automatically when someone flags it for the first time. – legends2k Aug 16 '13 at 13:02
  • 1
    Also no accepted answer in linked questions present how to actually pass the data, or rather what is the right function declaration to pass `const char* argv[]` or eqivalents, at least from brief overview I made. – luk32 Aug 16 '13 at 13:05
  • @luk32: I see your point and I upvoted you too – legends2k Aug 16 '13 at 13:06
  • @legends2k lol, I didn't know it's automatic. Thanks for appreciating the effort. – luk32 Aug 16 '13 at 13:09
  • @luk32 How would allowing the implicit conversion help in compiling your first example? Dereferencing `a` twice will still leave you with a const char. – ComicSansMS Aug 16 '13 at 13:10
  • @luk32 Your first example is incorrect. The second line is invalid, not the first. And you don't show what `foo` is. – James Kanze Aug 16 '13 at 13:26
  • @luk32 - please add the link to the C++FAQ from znb to your answer. After that, everything is said about this topic. – Tobias Langner Aug 16 '13 at 13:27
  • Even if this is a duplicate, this answer is better than the accepted one on the other question. I would be inclined to vote the other as a *anti-causal* duplicate of this... – David Rodríguez - dribeas Aug 16 '13 at 13:29
  • @JamesKanze Yes, that's my bad, but I am pretty sure that you can drop constness somehow, just my example is bad, but I do recall seeing or constructing such example. I need to figure it out. I will surely edit the answer. – luk32 Aug 16 '13 at 13:38
  • @TobiasLangner I did not see the link before posting, also its 1st and top voted comment I do not feel the need to link it 2nd time since I didn't use it. It is visible enough IMO. – luk32 Aug 16 '13 at 13:40
  • @luk32 Look in the C++ FAQ (one of the links). – James Kanze Aug 16 '13 at 14:01