<p>The following code snippet (correctly) gives a warning in C and an error in C++ (using gcc &amp; g++ respectively, tested with versions 3.4.5 and 4.2.1; MSVC does not seem to care):</p>

<pre><code>char **a;
const char** b = a;
</code></pre>

<p>I can understand and accept this.<br>
The C++ solution to this problem is to change b to be a const char * const *, which disallows reassignment of the pointers and prevents you from circumventing const-correctness (<a href="http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17" rel="nofollow noreferrer">C++ FAQ</a>).<br></p>

<pre><code>char **a;
const char* const* b = a;
</code></pre>

<p>However, in pure C, the corrected version (using const char * const *) still gives a warning, and I don't understand why.
Is there a way to get around this without using a cast?</p>

<p>To clarify:<br>
1) Why does this generate a warning in C?  It should be entirely const-safe, and the C++ compiler seems to recognize it as such.<br>
2) What is the correct way to go about accepting this char** as a parameter while saying (and having the compiler enforce) that I will not be modifying the characters it points to?
For example, if I wanted to write a function:</p>

<pre><code>void f(const char* const* in) {
  // Only reads the data from in, does not write to it
}
</code></pre>

<p>And I wanted to invoke it on a char**, what would be the correct type for the parameter?</p>

[{'answer_id': 78202, 'author': 'Kevin', 'author_id': 6386, 'author_profile': 'https://Stackoverflow.com/users/6386', 'pm_score': 7, 'selected': True, 'text': "<p>I had this same problem a few years ago and it irked me to no end.</p>\n\n<p>The rules in C are more simply stated (i.e. they don't list exceptions like converting <code>char**</code> to <code>const char*const*</code>).  Consequenlty, it's just not allowed.  With the C++ standard, they included more rules to allow cases like this.</p>\n\n<p>In the end, it's just a problem in the C standard.  I hope the next standard (or technical report) will address this.</p>\n"}, {'answer_id': 78218, 'author': 'Aaron', 'author_id': 14153, 'author_profile': 'https://Stackoverflow.com/users/14153', 'pm_score': 3, 'selected': False, 'text': '<blockquote>\n  <p>However, in pure C, this still gives a warning, and I don\'t understand why</p>\n</blockquote>\n\n<p>You\'ve already identified the problem -- this code is not const-correct.  "Const correct" means that, except for <code>const_cast</code> and C-style casts removing <code>const</code>, you can never modify a <code>const</code> object through those const pointers or references.</p>\n\n<p>The value of <code>const</code>-correctness -- <code>const</code> is there, in large part, to detect programmer errors.  If you declare something as <code>const</code>, you\'re stating that you don\'t think it should be modified -- or at least, those with access to the <code>const</code> version only should not be able to modifying it.  Consider:</p>\n\n<pre><code>void foo(const int*);\n</code></pre>\n\n<p>As declared, <code>foo</code> doesn\'t have <em>permission</em> to modify the integer pointed to by its argument.  </p>\n\n<p>If you\'re not sure why the code you posted isn\'t <code>const</code>-correct, consider the following code, only slightly different from HappyDude\'s code:</p>\n\n<pre><code>char *y;\n\nchar **a = &amp;y; // a points to y\nconst char **b = a; // now b also points to y\n\n// const protection has been violated, because:\n\nconst char x = 42; // x must never be modified\n*b = &amp;x; // the type of *b is const char *, so set it \n         //     with &amp;x which is const char* ..\n         //     ..  so y is set to &amp;x... oops;\n*y = 43; // y == &amp;x... so attempting to modify const \n         //     variable.  oops!  undefined behavior!\ncout &lt;&lt; x &lt;&lt; endl;\n</code></pre>\n\n<p>Non-<code>const</code> types can only convert to const types in particular ways to prevent any circumvention of <code>const</code> on a data-type without an explicit cast.  </p>\n\n<p>Objects initially declared <code>const</code> are particularly special -- the compiler can assume they never change.  However, if <code>b</code> can be assigned the value of <code>a</code> without a cast, then you could inadvertently attempt to modify a <code>const</code> variable.  This would not only break the check you asked the compiler to make, to disallow you from changing that variables value -- it would also allow you break the compiler optimizations!</p>\n\n<p>On some compilers, this will print <code>42</code>, on some <code>43</code>, and others, the program will crash.  </p>\n\n<p><strong>Edit-add:</strong></p>\n\n<p>HappyDude:  Your comment is spot on.  Either the C langauge, or the C compiler you\'re using, treats <code>const char * const *</code> fundamentally differently than the C++ language treats it.  Perhaps consider silencing the compiler warning for this source line only.</p>\n'}, {'answer_id': 78410, 'author': 'user7116', 'author_id': 7116, 'author_profile': 'https://Stackoverflow.com/users/7116', 'pm_score': 0, 'selected': False, 'text': '<p>I\'m not able to get an error when implicitly casting char** to const char * const *, at least on MSVC 14 (VS2k5) and g++ 3.3.3. GCC 3.3.3 issues a warning, which I\'m not exactly sure if it is correct in doing.</p>\n\n<p>test.c:</p>\n\n<pre><code>#include &lt;stdlib.h&gt; \n#include &lt;stdio.h&gt;\nvoid foo(const char * const * bar)\n{\n    printf("bar %s null\\n", bar ? "is not" : "is");\n}\n\nint main(int argc, char **argv) \n{\n    char **x = NULL; \n    const char* const*y = x;\n    foo(x);\n    foo(y);\n    return 0; \n}\n</code></pre>\n\n<p>Output with compile as C code: cl /TC /W4 /Wp64 test.c</p>\n\n<pre><code>test.c(8) : warning C4100: \'argv\' : unreferenced formal parameter\ntest.c(8) : warning C4100: \'argc\' : unreferenced formal parameter\n</code></pre>\n\n<p>Output with compile as C++ code: cl /TP /W4 /Wp64 test.c</p>\n\n<pre><code>test.c(8) : warning C4100: \'argv\' : unreferenced formal parameter\ntest.c(8) : warning C4100: \'argc\' : unreferenced formal parameter\n</code></pre>\n\n<p>Output with gcc: gcc -Wall test.c</p>\n\n<pre><code>test2.c: In function `main\':\ntest2.c:11: warning: initialization from incompatible pointer type\ntest2.c:12: warning: passing arg 1 of `foo\' from incompatible pointer type\n</code></pre>\n\n<p>Output with g++: g++ -Wall test.C</p>\n\n<p><em>no output</em></p>\n'}, {'answer_id': 78427, 'author': 'Skizz', 'author_id': 1898, 'author_profile': 'https://Stackoverflow.com/users/1898', 'pm_score': 0, 'selected': False, 'text': "<p>I'm pretty sure that the const keyword does not imply the data can't be changed/is constant, only that the data will be treated as read-only. Consider this:</p>\n\n<pre><code>const volatile int *const serial_port = SERIAL_PORT;\n</code></pre>\n\n<p>which is valid code. How can volatile and const co-exist? Simple. volatile tells the compiler to always read the memory when using the data and const tells the compiler to create an error when an attempt is made to write to the memory using the serial_port pointer.</p>\n\n<p>Does const help the compiler's optimiser? No. Not at all. Because constness can be added to and removed from data through casting, the compiler cannot figure out if const data really is constant (since the cast could be done in a different translation unit). In C++ you also have the mutable keyword to complicate matters further.</p>\n\n<pre><code>char *const p = (char *) 0xb000;\n//error: p = (char *) 0xc000;\nchar **q = (char **)&amp;p;\n*q = (char *)0xc000; // p is now 0xc000\n</code></pre>\n\n<p>What happens when an attempt is made to write to memory that really is read only (ROM, for example) probably isn't defined in the standard at all.</p>\n"}, {'answer_id': 78534, 'author': 'Fabio Ceconello', 'author_id': 8999, 'author_profile': 'https://Stackoverflow.com/users/8999', 'pm_score': 4, 'selected': False, 'text': "<p>To be considered compatible, the source pointer should be const in the immediately anterior indirection level. So, this will give you the warning in GCC:</p>\n\n<pre><code>char **a;\nconst char* const* b = a;\n</code></pre>\n\n<p>But this won't:</p>\n\n<pre><code>const char **a;\nconst char* const* b = a;\n</code></pre>\n\n<p>Alternatively, you can cast it:</p>\n\n<pre><code>char **a;\nconst char* const* b = (const char **)a;\n</code></pre>\n\n<p>You would need the same cast to invoke the function f() as you mentioned. As far as I know, there's no way to make an implicit conversion in this case (except in C++). </p>\n"}, {'answer_id': 98399, 'author': 'wnoise', 'author_id': 15464, 'author_profile': 'https://Stackoverflow.com/users/15464', 'pm_score': 1, 'selected': False, 'text': "<p>This is annoying, but if you're willing to add another level of redirection, you can often do the following to push down into the pointer-to-pointer:</p>\n\n<pre><code>char c = 'c';\nchar *p = &amp;c;\nchar **a = &amp;p;\n\nconst char *bi = *a;\nconst char * const * b = &amp;bi;\n</code></pre>\n\n<p>It has a slightly different meaning, but it's usually workable, and it doesn't use a cast.</p>\n"}]
['https://Stackoverflow.com/questions/78125', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/14266/']