3

I read this answer, but I am still not clear:

Something like:

#include <stddef.h>

size_t
foo(const char ** str)
{
  size_t i = 0;
  while (*str[0])
    i++;
  return i;
}

int main (int argc, char ** argv)
{
  foo(argv);
}

compiled as

$ gcc main.c
main.c: In function 'main':
main.c:14:7: warning: passing argument 1 of 'foo' from incompatible pointer type [-Wincompatible-pointer-types]
   14 |   foo(argv);
      |       ^~~~
      |       |
      |       char **
main.c:4:19: note: expected 'const char **' but argument is of type 'char **'
    4 | foo(const char ** str)

My fundamental question is: why can't I make something more const? What I am looking to accomplish is to say: I will not modify the characters, in this function.

To me, this seems different than the case the other answer gave, where you finagle your way into violating the const nature of a char.

user129393192
  • 797
  • 1
  • 8
  • 1
    "What I am looking to accomplish is to say: I will not modify the characters, in this function." C doesn't let you conveniently express this promise. In C++ you can write `const char* const* str` and it works perfectly fine, but alas C lacks implicit conversion from `T**` to `const T* const*`. – n. m. could be an AI Jun 22 '23 at 20:49
  • FYI... `while (*str[0]) i++;` is an infinite loop inside your `foo` function. I'm not sure if that matters to what you are asking. But I assume you really mean `while (*str[i]) i++;` – selbie Jun 22 '23 at 21:56
  • @user129393192, "why can't I make something more const" --> IIRC, C23 has an update to cope with this issue and allow it. – chux - Reinstate Monica Jun 22 '23 at 22:54
  • But then what would happen to the issue Eric mentioned in his answer? @chux-ReinstateMonica – user129393192 Jun 23 '23 at 03:09
  • @user129393192 Concerning detailed explanation of C23, best to wait for it to be released first. – chux - Reinstate Monica Jun 23 '23 at 03:35

1 Answers1

0

My fundamental question is: why can't I make something more const?

A char ** is a pointer to char *. Changing it to const char ** does not make it a pointer to a const of the type char *; that would be char * const *. It changes it to be a pointer to a different type.

You can change char ** to char * const *; an implicit conversion of that type will be accepted.

The issue is:

  • The type char * is protected from being assigned a const char *. Given char *p; and const char *cp;, p = cp; is not allowed.
  • The type const char * does not have that protection, because it is of course okay to assign a const char * to a const char *.
  • If you change char ** to const char **, you are removing protection.
  • Given char *pp = &p;, pp points to a protected thing.
  • If pp is passed to void foo(const char **cpp), the type const char **cpp says *cpp is not protected. Therefore foo can do *cpp = &cp;, which changes pp to point to a const char *, which should not be allowed.

To me, this seems different than the case the other answer gave,…

No, it is the same:

static const char *s = "Test";


void foo(const char **cpp)
{
    *cpp = s;
}


#include <stddef.h>


int main(void)
{
    char *p = NULL;
    char **pp = &p;
    foo(pp);  // Pass "char **" for "const char **", which is disallowed.

    *p = 0; //  Now p points to s, so this attempts to change a const char.
}
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • I was not able to follow the issue. Specifically, what protection are you removing? – user129393192 Jun 22 '23 at 21:05
  • @user129393192: Given `char *p;` and `const char *cp;`, `p = cp;` is not allowed. A `char *` is protected from being assigned a value of type `const char *`. – Eric Postpischil Jun 22 '23 at 22:13
  • 1
    Is there a typo in the bullet points? I cannot make sense of it still. Specifically, should the fourth have `char ** pp = &p`? And the 3rd, how do you remove protection by assigning `char**` to a `const char**`, that seems like additional protection and is the main point of my confusion, which I think relates to the 4th, where you say `pp` points to a protected thing. – user129393192 Jun 23 '23 at 03:03