C++ Logo


Advanced search

Re: reading values as bytes without memcpu, from enum unsigned char?

From: language.lawyer_at <language.lawyer_at_[hidden]>
Date: Mon, 10 Aug 2020 19:45:20 +0300
On 10/08/2020 19:17, Thiago Macieira via Std-Discussion wrote:
> On Friday, 7 August 2020 12:12:22 PDT language.lawyer--- via Std-Discussion
> wrote:
>>>> ```
>>>> int i = UCHAR_MAX + 1;
>>>> auto uc = *reinterpret_cast<unsigned char*>(&i); // UB because of
>>>> [expr.pre]/4 ```
>>> I don't see how [expr]/4 applies here. You're accessing an `unsigned
>>> char` in a place where there is no `unsigned char` object. There's no
>>> expectation that this value won't be "mathematically defined" or
>>> otherwise "not in the range of representable values for its type". So
>>> it's not UB by [expr]/4.
>> See my analysis of a similar code
>> https://lists.isocpp.org/sg12/2019/06/0802.php
> I'm not sure if it's the same thing. In that example, by attempting to bind a reference

There is no attempt to bind a reference there.

> to something that is of the wrong type, the language could say that
> there's an implicit conversion and you bind to the temporary resulting from
> that. Which would make your code ill-formed because you can't bind a non-const
> lvalue to a prvalue.
> Since that isn't the case (it is valid code), we have to see it the same way
> as:
> unsigned u = *reinterpret_cast<unsigned *>(&i);

Isn't it how the Standard defines `reinterpret_cast<unsigned&>(i)`?

> And that's still different from the above because of the type. One is unsigned
> char (a byte) which is allowed by the standard to alias everything. The other
> isn't.

The type is different, but `unsigned int` is allowed to alias `int`.

>>> The issue is that the value is not well-specified by the standard.
>> The value is 100% specified by the standard. It is the value of `i`, which
>> is `UCHAR_MAX + 1`.
> If you meant that the value of i is the value of i, then it's tautological.

I meant that the result (value) of the lvalue-to-rvalue conversion applied to `*reinterpret_cast<unsigned char*>(&i)` (or `*reinterpret_cast<unsigned*>(&i)`) is the value of `i`. Kind of, because [expr.pre]/4 ([expr]/4) immediately tells that this is UB.

> If you meant that the value of a uchar resulting from this conversion should
> be defined by the standard, then it's impossible nonsense.

I didn't mean how it should be defined, I wrote how it is currently [un]defined.
> The value is neither specified

How https://timsong-cpp.github.io/cppwp/n4659/conv.lval#3.4 is "not specified"?

Received on 2020-08-10 11:48:46