From Newsgroup: comp.lang.c
Andrey Tarasevich <
[email protected]> writes:
On Thu 4/9/2026 1:09 PM, Chris M. Thomasson wrote:
struct foo const* const ?
Again, the ability to implicitly convert `T **` to `const T* const*`
seems to be related to the above array pointer conversion issue (at
least superficially). In C++ both conversions are supported as
standard (i.e. implicit) conversions. In "classic" C neither is,
which is a bit annoying.
C23 resolved the array issue. But the `T ** -> const T* const*`
conversion is still unsupported as an implicit conversion even in C23.
The circumstances with arrays and with pointers are rather
different. With pointers, one can always convert to a more
const-laden version of a type by using a cast:
int
takes_ppi( int **p ){
return **p;
}
int
takes_ppci( const int **p ){
return **p;
}
int
takes_pcpi( int *const *p ){
return **p;
}
int
takes_pcpci( const int *const *p ){
return **p;
}
int
try_each_pointer_type( int **p ){
int a = takes_ppi( p );
int b = takes_ppci( (const int **) p );
int c = takes_pcpi( p );
int d = takes_pcpci( (const int *const*) p );
return a+b+c+d;
}
Notice in the case of takes_pcpi() that no cast is needed. That's
because the rule that 'X*' may be converted to 'const X*' applies
even when 'X' is a pointer type. Incidentally, the 'takes_ppci()'
case gives a warning under gcc with -Wall -Wextra, so using a cast
is "safe" in the sense that it is possible to get a warning for a
dangerous conversion.
The problem with arrays is that there is no way to convert from an
argument of type 'X*' to type 'const X*' when X is an array type,
because before C23 "const array" types _didn't exist_. Thus there
is no way to satisfy the rules for pointer conversion just by
writing a cast. There is a way around the problem of wanting to
convert to, for example, a 'const int (*)[1]' type, but it's more
cumbersome:
int
takes_pai( int (*p)[1] ){
return (*p)[0];
}
int
takes_paci( const int (*p)[1] ){
return (*p)[0];
}
int
try_each_array_type( int (*p)[1] ){
union { int (*pai)[1]; const int (*paci)[1]; } both = {p};
int a = takes_pai( p );
int b = takes_paci( both.paci );
return a+b;
}
Mixing const-ness and pointer-ness is tricky, or at least
non-obvious. I'm not sure the C decision regarding implicit
conversions when const-ness and pointer-ness are both involved is a
bad choice. Since it doesn't come up very often, and the remedy for
when it does come up is so straightforward, it might be better to
adopt a simple rule, as C has done, than to complicate the language
definition with a more elaborate rule. But arrays are another
kettle of fish altogether, and I'm happy to see the issues around
const arrays are finally getting the attention they deserve (which I
have been advocating for more than 10 years now).
--- Synchronet 3.21f-Linux NewsLink 1.2