3

I'm reading type aliasing rules but can't figure out if this code has UB in it:

std::vector<std::byte> vec = {std::byte{'a'}, std::byte{'b'}};
auto sv = std::string_view(reinterpret_cast<char*>(vec.data()), vec.size());
std::cout << sv << '\n';

I'm fairly sure it does not, but I often get surprised by C++. Is reinterpret_cast between char*, unsigned char* and std::byte* always allowed?

Additionally, is addition of const legal in such cast, e.g:

std::array<char, 2> arr = {'a', 'b'};
auto* p = reinterpret_cast<const std::byte*>(arr.data());

Again, I suspect it is legal since it says

AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType

but I would like to be sure with reinterpret_casting once and for all.

Rudolf Lovrenčić
  • 147
  • 1
  • 2
  • 9
  • Related question: [What is the strict aliasing rule?](https://stackoverflow.com/q/98650/12149471) However, that question is not very specific, as it does not distinguish between C and C++, although the rules are different in both languages. – Andreas Wenzel Oct 02 '21 at 08:20
  • If we assume that `vec.data()` gives a pointer to an array element and then pointer arithmetic is performed on `reinterpret_cast`-ed value of this pointer in the `sv`, then it violates https://timsong-cpp.github.io/cppwp/n4868/expr.add#6.sentence-1. – Language Lawyer Oct 02 '21 at 14:17
  • @LanguageLawyer can you expand on that? – Rudolf Lovrenčić Oct 08 '21 at 10:13
  • Expand on what? A pointer of type `char*` pointing to an object of type `std::byte` can't be used in pointer arithmetic. It would be much easier to reason about your code if you didn't hide everything behind library function calls and explicitly exposed essential things which they do. – Language Lawyer Oct 08 '21 at 11:30
  • I don't see where library could make such arithmetic. `std::byte b[2]; reinterpret_cast(&b[1]) - reinterpret_cast(&b[1]);` I don't think this is UB. `vec.data()` provides pointer to array element, but does it is reinterpreted as `char*`. This `char*` may then, for example, be subtracted from another `char*`, no? – Rudolf Lovrenčić Oct 10 '21 at 08:57

1 Answers1

5

The code is ok.

char* and std::byte* are allowed by the standard to alias any pointer type. (Be careful as the reverse is not true).

([basic.types]/2):

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes ([intro.memory]) making up the object can be copied into an array of char, unsigned char, or std​::​byte ([cstddef.syn]).43 If the content of that array is copied back into the object, the object shall subsequently hold its original value.

([basic.lval]/8.8):

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • a char, unsigned char, or std​::​byte type.

And yes you can add const.

bolov
  • 72,283
  • 15
  • 145
  • 224