Reputation: 409
I have already read a number of questions about this warning (Dereferencing type-punned pointer will break strict-aliasing rules, Dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing], What is the strict aliasing rule?, "dereferencing type-punned pointer will break strict-aliasing rules" warning and others) and got totally confused about my warning.
So I have a struct:
typedef struct {
unsigned char precision;
unsigned char scale;
unsigned char array[33];
} DBNUMERIC;
This struct is filled by FreeTDS library when retrieving data from MS SQL Server. I know that starting from array[1]
there is 64-bit integral number (in big-endian) and I want to get it. I use the following code:
int64_t result = 0;
result = be64toh(*((decltype(result)*)(numeric.array + 1)));
But GCC gives me the warning dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
. But if I use the code:
int64_t result = 0;
decltype(result)* temp_ptr = (decltype(result)*)(numeric.array + 1);
decltype(result) temp = *temp_ptr;
result = be64toh(temp);
there are no warnings about violating strict-aliasing rules. I don't think that this code differs from the original, therefore I am confused. How can I convert 8 bytes from the array to a int64_t
variable?
Upvotes: 3
Views: 938
Reputation: 158469
Both of your cases violate the strict aliasing rules. gcc's strict-aliasing warnings are subject to false negatives and false positives depending on the warning and optimization levels.
If you want to type-pun in a way not allowed by the strict aliasing rules then you should just use std::memcpy:
std::memcpy(&result, numeric.array+1, sizeof(int64_t ));
We can see from the following sources; this article Type Punning, Strict Aliasing, and Optimization and the std-dicussion conversation on type punning and unions I quote in my answer here tell us that the compiler should be smart enough to optimize for the use of memcpy
to generate efficient code.
Upvotes: 5