AW: A: a new bug to old plain C
Jonathan Wakely
jwakely.gcc@gmail.com
Fri Nov 21 14:16:09 GMT 2025
On Fri, 21 Nov 2025 at 13:58, David Brown via Gcc-help
<gcc-help@gcc.gnu.org> wrote:
>
> On 21/11/2025 14:16, stefan@franke.ms wrote:
> >> -----Ursprüngliche Nachricht-----
> >> Von: Gcc-help <gcc-help-bounces~bebbo=bejy.net@gcc.gnu.org> Im Auftrag von
> >> Jonathan Wakely via Gcc-help
> >> Gesendet: Freitag, 21. November 2025 12:47
> >> An: Chris S <cs2991@gmail.com>
> >> Cc: Александр Поваляев <apovalyaev@gmail.com>; gcc-help <gcc-
> >> help@gcc.gnu.org>
> >> Betreff: Re: A: a new bug to old plain C
> >>
> >> On Fri, 21 Nov 2025 at 03:25, Chris S via Gcc-help <gcc-help@gcc.gnu.org>
> >> wrote:
> >>>
> >>> You're applying two consts to the same thing, so it's an error.
> >>
> >> No, that's not happening here.
> >>
> >> The explanation is
> >> https://isocpp.org/wiki/faq/const-correctness#constptrptr-conversion
> >>
> >>>
> >>> "Const int" and "int const" are the same (look up East vs West const),
> >>> but "const int const" is an error. Declaring a pointer to that
> >>> invalid type declaration is still invalid.
> >>>
> >>> On Thu, Nov 20, 2025, 5:27 PM Александр Поваляев via Gcc-help <
> >>> gcc-help@gcc.gnu.org> wrote:
> >>>
> >>>> struct zzz {
> >>>> unsigned x, y;
> >>>> };
> >>>>
> >>>> void square(struct zzz ** arr_of_ptr, unsigned count) {
> >>>>
> >>>> *// The first "const" produce an error (not a warning) within some
> >>>> GCC toolchains, for example ARM GCC trunk (linux), see goldbolt.org
> >>>> <http://goldbolt.org>*
> >>>> struct zzz const * const * const end_of_arr = arr_of_ptr + count;
> >>>>
> >>>> *// Without the first const "struct zzz * const * const end_of_arr =
> >>>> arr_of_ptr + count;" it works fine!!!*
> >>>>
> >>>> }
> >>>>
> >>>> Respectfully,
> >>>> Aleksandr G Povaliaev.
> >>>>
> >
> > Consider:
> >
> > char const * foo1(char * x) {
> > char const * y = x;
> > *x = 'a';
> > return y;
> > }
> >
> > char const ** foo2(char ** x) {
> > char const ** y = x;
> > **x = 'a';
> > return y;
> > }
> >
> > typedef char * cp;
> > cp const * foo3(cp * x) {
> > cp const * y = x;
> > **x = 'a';
> > return y;
> > }
> >
> > All three should compile fine, but one does not.
> > It is not consistent.
> >
> >
>
> foo2 does not compile - it fails at the initialisation of "y". That is
> because "x" is a pointer to a "char *", while "y" is a pointer to a
> "const char *" - a pointer to a pointer to a const char. These are
> different types, and are not compatible (see §6.7.3p10 in the C
> standards if you want read the law). You can implicitly convert a
> "thing" to a "const thing", but that is not what is happening here.
>
> With foo3, the "const" in y refers to the "char *" pointer. Thus "y" is
> now a pointer to a constant pointer to a char. This is more akin to
> foo1. You can add a "const" to the thing you are point to, but not to a
> thing you are pointing to indirectly (via one or more extra pointers).
>
> You might find it illustrative to change the "**x = 'a'" lines to "**y =
> 'a'", and put the code into godbolt.org to see what compiler errors you get.
>
>
> It is all a bit subtle, and it's easy to get mixup up if you don't use
> double pointers often. I rarely see them in my own code, and have to be
> careful when dealing with them - I will often use typedefs to keep
> things simpler. (Opinions and styles will vary a lot as to whether
> typedefs help there - probably if you work with code where multiple
> indirections are common, it is better to use them "raw" until you are so
> familiar that you get an instinctive understanding.)
>
> Lots of types in C might appear to be basically the same thing and yet
> are not considered compatible by the language - usually it is for good
> reasons, such as the faq entry Jonathan gave above. (The faq was for
> C++, but applies equally to C.)
Here's the same topic in the C FAQ:
https://github.com/llvm/llvm-project/pull/167010
More information about the Gcc-help
mailing list