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