Path: csiph.com!weretis.net!feeder8.news.weretis.net!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: "Catch-23: The New C Standard,Sets the World on Fire" by Terence Kelly with Special Guest Borer Yekai Pan Date: Wed, 12 Apr 2023 02:35:46 -0700 Organization: A noiseless patient Spider Lines: 82 Message-ID: <86edop30jx.fsf@linuxsc.com> References: <20230407042121.909@kylheku.com> <86r0st3zj0.fsf@linuxsc.com> <871qkshmhv.fsf@nosuchdomain.example.com> <681e3cb9-65b6-472b-b710-4e492154f238n@googlegroups.com> <86ile13jiq.fsf@linuxsc.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: dont-email.me; posting-host="00dd14a5b0fe7fcb33b04c058bf64644"; logging-data="3140856"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19z8x2FZGP1cy3LJgYOwO7oQt1tapvBzdA=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:74Off7ptYdIglwBwVSUEeY2ox9A= sha1:qwsqPstWEejhmgyIe2ZamSinT2A= Xref: csiph.com comp.lang.c:169995 "james...@alumni.caltech.edu" writes: > On Tuesday, April 11, 2023 at 10:46:24?PM UTC-4, Tim Rentsch wrote: > >> James Kuyper writes: > > ... > >>> The fundamental problem is that, in C, a typedef is nothing more >>> than an synonym for a type. In any context where you use a typedef, >>> you could also use the explicit type itself. [...] >> >> Strictly speaking this assertion isn't quite right. Here is an >> example: >> >> typedef long Elongator( int ); >> >> extern const Elongator *elongator; > > I'm confused by that declaration - what is the 'const' supposed to > mean in that context? 'Elongator' is a function type (that maps an int to a long). 'const Elongator' is a 'const' function type; in other words the qualifier 'const' applies to the function type as a whole, not just to the return type of the function. > Normally, I would read that declaration as > saying that elongator is an identifier with external linkage, and > that (*elongator)(5) returns a "const long", which makes no sense to > me. If 'elongator' had been declared as follows: const long (*elongator)( int ); that would give the result you describe. But in effect the declaration of 'elongator' is the following (not legal C, but meant to show what is taking place): extern const (long (int)) *elongator; so the 'const' modifies the function type itself as a whole, and not just the return type of the function. The syntax used there is not allowed in C, which is why a typedef is needed. >> There is no way to declare the pointer object 'elongator' without >> the use of a typedef. >> It may be worth noting that using a type qualifier directly on a >> function type is explicitly undefined behavior (but not a constraint >> violation). > > gcc shares my confusion about that declaration, referring to > precisely that rule: > elongator.h:2:25: warning: ISO C forbids qualified > function types [-Wpedantic] > 2 | extern const Elongator *elongator; > | ^~~~~~~~~ Actually I think gcc is not confused, but has (for some unknown reason) chosen to give a confusing error message. In point of fact ISO C does not forbid qualified function types, but simply says they are undefined behavior. > That error message disappears if I move the 'const', so that it > qualifies elongator, which makes a lot more sense to me: > extern Elongator * const elongator; > > and it accepts, as compatible, the following declaration of the > same identifier: > > extern long(*const elongator)(int); Yes, moving 'const' to the other side of the '*' changes the meaning of the declaration, just like the two declarations const int *pci; int *const cpi; have different meanings for the types of the respective items being declared.