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
>