A: a new bug to old plain C

Александр Поваляев apovalyaev@gmail.com
Wed Nov 26 13:48:22 GMT 2025


Hi there!

The logic provided by you is not straightforward and, truly speaking, is
NOT CORRECT:
You've just proved that "Foo*" -> "const Foo* const" conversion (conversion
between two types with different qualifiers) might be done without any
error or warning.
You wrote that the following code snippet
"
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!

}"
works fine since it is in agreement with one of the 6.5.17.2 condition,
literally:
"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;
".

I want to emphasize here "One of the following shall hold"!.
So, if one of the following is being hold, the conversion/assignment is
permitted.

But USE THE SAME TRICK WITH DISJUNCTION AND CONJUNCTION to prove that
"Foo**" -> const Foo * const * const" is not correct.
IT IS WRONG WAY.
To be logically correct you need to show that NO ONE OF THE 6.5.17.2
STATEMENT is TRUE for "Foo**" -> const Foo * const * const" logic.

But it is ok. It is usually being studied at some university courses, so if
you decide to enter some high education school you will learn all of these
things.

-------------------

Respectfully,
Aleksandr G Povaliaev.


ср, 26 нояб. 2025 г. в 13:24, LIU Hao <lh_mouse@126.com>:

> 在 2025-11-26 18:12, Александр Поваляев 写道:
> > [[[Aleksandr]]] So these types are not compatible. But the
> assignment goes without any error or warning.
>
> Because you have asked someone to quote the standard, so you must think in
> the standard way.
>
> Compatible types has nothing to do with any error or warnings. If two
> types are compatible, then they can
> be re-interpreted as each other without conversion.
>
> These two variables are also of incompatible types, but nevertheless, they
> can be assigned to each other:
>
>     int a = 1;
>     float b = 2;
>     a = b;   // conversion happens
>     b = a;   // conversion happens
>
>
> >     But the conversion is allowed by the second quoted paragraph.
> Although those pointers point to
> >     incompatible types, the conversion happens as a simple assignment,
> so qualified compatible types are
> >     also
> >     allowed. (The left operand can't have fewer qualifiers than the
> right operand.)
> >
> > [[[Aleksandr]]] What particular citation do you mean?
>
> See this:
>
>     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;
>
>
> > [[[Aleksandr]]] Also. An important point to be mentioned:
> "Foo**"->"const Foo * const * const" conversion
> > being compiled with "-Wno-incompatible-pointer-types" still produce an
> error :(
>
> It's because they don't point to qualified compatible types. If you remove
> top-level * (to undo 'point
> to'), then also remove top-level `const` (to undo 'qualified'), you get
> are `Foo *` and `const Foo *`,
> and they are clearly not compatible.
>
>
> --
> Best regards,
> LIU Hao
>


More information about the Gcc-help mailing list