Re: A: a new bug to old plain C

Александр Поваляев via Gcc-h elp <[email protected]>
Newsgroups gmane.comp.gcc.help
Message-ID <CAGT+J5xybv33=Ppry7V2XinOf1AAqyT4Uv6gZ8OTuTV869JAFw@mail.gmail.com>
Hi there!

The code below works fine on all the GCC compilers. It doesn't provide
either errors or warnings.

"
struct zzz {
unsigned x, y;
};


void square(struct zzz * arr_of_ptr, unsigned count) {

struct zzz * const ptr1 = arr_of_ptr; // OK!
struct zzz const * ptr2 = arr_of_ptr; // OK!
struct zzz const * const ptr3 = arr_of_ptr; // OK!

}
"

Respectfully,
Aleksandr G Povaliaev.

ср, 26 нояб. 2025 г. в 09:56, LIU Hao <[email protected]>:

> 在 2025-11-26 14:14, Александр Поваляев via Gcc-help 写道:
> > Hi there! So, any update on this?
> >
> > Could somebody point out where in the C standard a conversion "Foo**" ->
> > "const Foo * const * const" is prohibited?
> > Any link? Some quote from any book on C language?
> >
>
> You may download a copy of the draft of the C standard at
>
>     https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
>
> I will quote the standard for you. I will add markers such as >>>>>>> and
> <<<<<<< which are not part of
> the standard.
>
>
> Your original question was about initialization:
>
>     6.7.11 Initialization
>
>     12 The initializer for a scalar shall be a single expression,
> optionally enclosed
>        in braces, or it shall be an empty initializer. If the initializer
> is not the
>        empty initializer, the initial value of the object is that of the
> expression
>        (after conversion); the same type constraints and conversions
> >>>>>>> as for
>        simple assignment apply <<<<<<<, taking the type of the scalar to
> be the
>        unqualified version of its declared type.
>
>
> The constraint by simple assignment is:
>
>     6.5.17 Assignment operators
>     6.5.17.2 Simple assignment
>
>     1 One of the following shall hold
>
>       — the left operand has atomic, qualified, or unqualified pointer
> type, and
>         (considering the type the left operand would have after lvalue
> conversion)
>         both operands are pointers to >>>>>>> qualified or unqualified
> versions of
>         compatible types <<<<<<<, and the type pointed to by the left
> operand has all
>         the qualifiers of the type pointed to by the right operand;
>
>
> And finally, the rules about compatible qualifiers are:
>
>     6.7.4 Type qualifiers
>     6.7.4.1 General
>
>     11 For two qualified types to be compatible, both shall have >>>>>>>
> the
>        identically qualified version <<<<<<< of a compatible type; the
> order of
>        type qualifiers within a list of specifiers or qualifiers does not
> affect the
>        specified type.
>
>
> So, why doesn't `Foo**` convert to `const Foo* const* const` implicitly?
> It's simple. First, top-level
> qualifiers are not meaningful and are ignored, like `int` converts to
> `const int`. Then, the first type
> is a pointer to `Foo*`, but the second type is a pointer to `const Foo*
> const`, and these are not
> 'qualified versions of compatible types', because `Foo*` and `const Foo*`
> are not 'identically qualified'.
>
> On the other hand, `Foo**` converts to `Foo* const*` implicitly. It's
> because the first type is a pointer
> to `Foo*`, and the second type is a pointer to `Foo* const`, and these are
> 'qualified versions of
> compatible types'. Actually. they are qualified versions of the same type.
>
> The standard may look weird, but it's just the standard.
>
>
> --
> Best regards,
> LIU Hao
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.