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.