alfC
alfC

Reputation: 16272

Does simple overlap of memory in variables violate aliasing rules?

In order to have effectively compile-time-sized subranges views of compile-time-sized arrays.

I have been using this technique for a while and since I never got a warning or an error I thought it was OK.

std::array<int,3> aa = {{1,2,3}};
std::array<int,2>& ee = reinterpret_cast<std::array<int,2>&>(aa[1]); // subrange {{2,3}}
assert(ee[0] == 2);

Until I found these comments https://stackoverflow.com/a/36046533/225186

I can make gcc produce a warning with this

int aaa = 5;
double& eee = reinterpret_cast<double&>(aaa);

or this

std::array<int,3> aaaa = 5;
std::array<double,2>& eeee = reinterpret_cast<std::array<double,2>&>(aaaa);

...but not with the first block of code.

It seems that the aliasing rules are not enforced if the two references are not exactly in the same address?


Everybody seems to agree that this is at least UB. Would this be OK? Or is even worst?

int aa[3] = {1,2,3};
int* ee = new(&aa[1]) int[2];

It would be perfect if I could say int ee[2] = new(&aa[1]) int[2]; because the type of ee will carry the new size and I can use subviews recursively.

Can I use std::basic_string_view<int> for this? At cppreference the only constraint is that int has to be char-like. (Which I think it is.)

Upvotes: 1

Views: 97

Answers (1)

Vittorio Romeo
Vittorio Romeo

Reputation: 93314

std::array<int,3> aa = {{1,2,3}};
std::array<int,2>& ee = reinterpret_cast<std::array<int,2>&>(aa[1]);

This definitely breaks strict aliasing rules, and an access to ee is undefined behavior.

See cppreference/reinterpret_cast/type aliasing:

enter image description here


...but not with the first block of code.

If your compiler is not producing a warning, it doesn't mean that everything is OK - warnings are not mandated by the Standard. Compilers try to be as helpful as possible, but they will not detect all Standard violations.

Upvotes: 1

Related Questions