strict-aliasing

Reinterpret struct with members of the same type as an array in a standard compliant way [duplicate]

偶尔善良 提交于 2019-11-27 07:41:41
问题 This question already has an answer here: Casting double array to a struct of doubles 6 answers In various 3d math codebases I sometimes encounter something like this: struct vec { float x, y, z; float& operator[](std::size_t i) { assert(i < 3); return (&x)[i]; } }; Which, AFAIK is illegal because implementations are allowed to spuriously add padding between members, even if they are of the same type, though none will do so in practice. Can this be made legal by imposing constraints via

Does this really break strict-aliasing rules?

耗尽温柔 提交于 2019-11-27 04:28:57
When I compile this sample code using g++, I get this warning: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] The code: #include <iostream> int main() { alignas(int) char data[sizeof(int)]; int *myInt = new (data) int; *myInt = 34; std::cout << *reinterpret_cast<int*>(data); } In this case, doesn't data alias an int, and therefore casting it back to an int would not violate strict aliasing rules? Or am I missing something here? Edit: Strange, when I define data like this: alignas(int) char* data = new char[sizeof(int)]; The compiler warning goes

Strict pointer aliasing: is access through a 'volatile' pointer/reference a solution?

我怕爱的太早我们不能终老 提交于 2019-11-27 02:50:40
问题 On the heels of a specific problem, a self-answer and comments to it, I'd like to understand if it is a proper solution, workaround/hack or just plain wrong. Specifically, I rewrote code: T x = ...; if (*reinterpret_cast <int*> (&x) == 0) ... As: T x = ...; if (*reinterpret_cast <volatile int*> (&x) == 0) ... with a volatile qualifier to the pointer. Let's just assume that treating T as int in my situation makes sense. Does this accessing through a volatile reference solve pointer aliasing

strict aliasing in C

徘徊边缘 提交于 2019-11-27 02:10:09
Question about type punning: why does this code break strict aliasing rules: int main() { int a = 1; short j; printf("%i\n", j = *((short*)&a)); return 0; } and this is not: int main() { int a = 1; short j; int *p; p=&a; printf("%i\n", j = *((short*)p)); return 0; } Build by gcc -fstrict-aliasing . Thank you! They both violate the strict aliasing rule , I am going to quote my answer here which says ( emphasis mine going forward ): code violates the strict aliasing rules which makes it illegal to access an object through a pointer of a different type , although access through a char * is

Undefined behavior on reading object using non-character type when last written using character type

穿精又带淫゛_ 提交于 2019-11-27 02:09:01
问题 Assuming unsigned int has no trap representations, do either or both of the statements marked (A) and (B) below provoke undefined behavior, why or why not, and (especially if you think one of them is well-defined but the other isn't), do you consider that a defect in the standard? I am primarily interested in the current version of the C standard (i.e. C2011), but if this is different in older versions of the standard, or in C++, I would also like to know about that. ( _Alignas is used in

Has a std::byte pointer the same aliasing implications as char*?

安稳与你 提交于 2019-11-27 02:04:46
问题 C++ (and C) strict aliasing rules include that a char* and unsigned char* may alias any other pointer. AFAIK there is no analogous rule for uint8_t* . Thus my question: What are the aliasing rules for a std::byte pointer? The C++ reference currently just specifies: Like the character types (char, unsigned char, signed char) it can be used to access raw memory occupied by other objects (object representation), but unlike those types, it is not a character type and is not an arithmetic type.

Type punning with void * without breaking the strict aliasing rule in C99

风流意气都作罢 提交于 2019-11-27 00:56:21
问题 I recently came across the strict aliasing rule, but I'm having trouble understanding how to use void * to perform type punning without breaking the rule. I know this breaks the rule: int x = 0xDEADBEEF; short *y = (short *)&x; *y = 42; int z = x; And I know that I can safely use a union in C99 for type-punning: union{ int x; short y; } data; data.x = 0xDEADBEEF; data.y = 42; int z = data.x; But how do I use void * to safely perform type-punning in C99? Is the following correct: int x =

reinterpret_cast between char* and std::uint8_t* - safe?

荒凉一梦 提交于 2019-11-27 00:25:41
问题 Now we all sometimes have to work with binary data. In C++ we work with sequences of bytes, and since the beginning char was the our building block. Defined to have sizeof of 1, it is the byte. And all library I/O functions use char by default. All is good but there was always a little concern, a little oddity that bugged some people - the number of bits in a byte is implementation-defined. So in C99, it was decided to introduce several typedefs to let the developers easily express themselves

“dereferencing type-punned pointer will break strict-aliasing rules” warning

99封情书 提交于 2019-11-27 00:13:08
I use a code where I cast an enum* to int*. Something like this: enum foo { ... } ... foo foobar; int *pi = reinterpret_cast<int*>(&foobar); When compiling the code (g++ 4.1.2), I get the following warning message: dereferencing type-punned pointer will break strict-aliasing rules I googled this message, and found that it happens only when strict aliasing optimization is on. I have the following questions: If I leave the code with this warning, will it generate potentially wrong code? Is there any way to work around this problem? If there isn't, is it possible to turn off strict aliasing from

Using this pointer causes strange deoptimization in hot loop

ぃ、小莉子 提交于 2019-11-27 00:04:48
问题 I recently came across a strange deoptimization (or rather missed optimization opportunity). Consider this function for efficient unpacking of arrays of 3-bit integers to 8-bit integers. It unpacks 16 ints in each loop iteration: void unpack3bit(uint8_t* target, char* source, int size) { while(size > 0){ uint64_t t = *reinterpret_cast<uint64_t*>(source); target[0] = t & 0x7; target[1] = (t >> 3) & 0x7; target[2] = (t >> 6) & 0x7; target[3] = (t >> 9) & 0x7; target[4] = (t >> 12) & 0x7; target