Re: AW: A: a new bug to old plain C
Jonathan Wakely via Gcc-help <[email protected]>
| Newsgroups | gmane.comp.gcc.help |
|---|---|
| Message-ID | <CAH6eHdT5ti+5jkeWcbA1QZMKzu-sQQZ_nxDOLz1vLoGGVsgoEQ@mail.gmail.com> |
On Fri, 21 Nov 2025 at 14:16, Jonathan Wakely <[email protected]> wrote: > > On Fri, 21 Nov 2025 at 13:58, David Brown via Gcc-help > <[email protected]> wrote: > > > > On 21/11/2025 14:16, [email protected] wrote: > > >> -----Ursprüngliche Nachricht----- > > >> Von: Gcc-help <[email protected]> Im Auftrag von > > >> Jonathan Wakely via Gcc-help > > >> Gesendet: Freitag, 21. November 2025 12:47 > > >> An: Chris S <[email protected]> > > >> Cc: Александр Поваляев <[email protected]>; gcc-help <gcc- > > >> [email protected]> > > >> Betreff: Re: A: a new bug to old plain C > > >> > > >> On Fri, 21 Nov 2025 at 03:25, Chris S via Gcc-help <[email protected]> > > >> 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 < > > >>> [email protected]> 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 Gah, sorry, pasted the wrong URL, *here* it is in the C FAQ: https://c-faq.com/ansi/constmismatch.html