Re: AW: A: a new bug to old plain C
Jonathan Wakely via Gcc-help <[email protected]>
| Newsgroups | gmane.comp.gcc.help |
|---|---|
| Message-ID | <CAH6eHdRBtjZ-Cfrq6U2fHLYA4nC7GqxycExH-4jT3QSukSTDGw@mail.gmail.com> |
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