On 23/06/2022 16:47, Frederick Virchanza Gotham wrote:
> On Thursday, June 23, 2022 at 3:03:31 PM UTC+1, David Brown wrote:
>
>> You are dereferencing the iterator, then taking its address.
>
>
> The expression, "s.cend()", is of type string::const_iterator, which is not a simple pointer (or at least it's not a simple pointer on my g++ compiler).
>
>
Yes. Despite that, I suspect that the "&*" can be turned into
calculating an address, without actually dereferencing it. And if the
generated code does not dereference it, memory access checkers will have
a hard time spotting the problem.
>> In C, "&*x" is treated exactly as "x" except for constraint checking and
>> making the result an lvalue.
>
>
> I think you mean R-value.
I actually meant to write /not/ an lvalue, which is basically the same
thing in C (but "not an lvalue" is the phrase used by the standard).
Sorry for missing that!
>
> I'm only concerned with C++ right now. Is there anything in the C++ standard that says you can dereference an invalid pointer so long as you immediately take the address of the pointed-to thing? Is the following program valid in C++20?
>
> int main(void)
> {
> char *p = nullptr;
>
> &*p;
> }
I could not find anything to that effect, but the C++ standards are big
- and they change faster than I read them! Maybe someone else here can
give you a better answer.
>
> By the way "&*" has an observable effect when used on an array, for example:
>
> Define an array: char buf[64];
>
> The expression "buf" is an L-value of type "char[64]"
>
It is, but it does not survive as an lvalue in most expressions - in
most uses, it gets converted to a pointer to its first element (an
rvalue). That includes "&*buf", but also most
> The expression "&*buf" is an R-value of type "char*"
>
Yes.
The exact passage from the C standard is :
"""
The unary & operator yields the address of its operand. If the operand
has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the
operand is the result of a unary * operator, neither that operator nor
the & operator is evaluated and the result is as if both were omitted,
except that the constraints on the operators still apply and the result
is not an lvalue. Similarly, if the operand is the result of a []
operator, neither the & operator nor the unary * that is implied by the
[] is evaluated and the result is as if the & operator were removed and
the [] operator were changed to a + operator.
"""
As I say, I didn't find anything similar in the C++ standard. But it's
quite possible that the compiler does a similar "remove the &* then
correct the type" operation in an early code simplification pass,
assuming of course that this is okay with respect to any overloaded
operators involved. Later passes, sanitisers, and run-time checks would
then not see the dereference.