Immediately: I will not talk about UB - frankly, I don’t see (especially in your case, for char ) reasons for it ... but this is one of my weak points. It will be very interesting to listen to why UB is here. If due to strict aliasing, then it seems that the appeal is allowed through char* ...
As a more practical person :), I will say that the main difference will appear when it is not POD, but some more interesting cases - for example, class objects. An example, pieces of which are here, is completely at https://ideone.com/RvQSax
In the first case, we have an assignment, and it is the assignment operator that is called:
long long L; Test * t = reinterpret_cast<Test*>(&L); *t = Test(5);
The main trouble is that the assignment is performed simply to a place in memory, so if the assignment operator first deals with the removal of the object to which we assign, we still get in trouble ... And if there was an object with a non-trivial destructor, then there will be more problems.
long long M; Test * u = new(&M) Test(6);
This method is much more correct - because the placing operator new assumes the presence of uninitialized memory, in which an object must be placed with the help of a constructor (well, as if the memory were allocated). No action is taken with an object allegedly placed in this memory before.
But! Anyway, the old problem remains - if there really was an object with a non-trivial destructor, then there would be problems.
PS Maybe @VladD meant exactly this, speaking about UB?
char*- yrHeTaTeJlbreinterpret_castalready there . - wololo