The codebase at work contains some code that looks roughly like this:
#define DATA_LENGTH 64
u_int32 SmartKey::SerialNumber()
{
unsigned char data[DATA_LENGTH];
// ... initialized data buffer
return *(u_int32*)data;
}
This code works correctly, but GCC gives the following warning:
warning: dereferencing pointer ‘serialNumber’ does break strict-aliasing rules
Can someone explain this warning? Is this code potentially dangerous? How can it be improved?
Update
With thanks to James McNellis' answer I came up with the following utility function:
template<class T, class Data>
T BinaryCast(const Data & inData)
{
T ret;
std::copy(&inData[0], &inData[0] + sizeof(ret), reinterpret_cast<char*>(&ret));
return ret;
}
u_int32 SmartKey::SerialNumber()
{
unsigned char data[DATA_LENGTH];
// ... initialized data buffer
return BinaryCast<u_int32>(data);
}
Feel free to suggest improvements!
To convert integer to binary, start with the integer in question and divide it by 2 keeping notice of the quotient and the remainder. Continue dividing the quotient by 2 until you get a quotient of zero. Then just write out the remainders in the reverse order.
Integer variables are variables that must take an integer value (0, 1, 2, ...). A special kind of integer variables is binary variables. Binary variables can only take the value 0 or 1. They are integer variables with a maximum of 1 on them (and don't forget there is always an implicit minimum of 0 on each variable).
Integer Representation. Integers are whole numbers or fixed-point numbers with the radix point fixed after the least-significant bit. They are contrast to real numbers or floating-point numbers, where the position of the radix point varies.
The warning is because you are violating the strict aliasing rule.
One way to do it correctly would be to copy the bytes from the data
buffer into a u_int32
object and return that object:
unsigned char data[DATA_LENGTH];
// ... initialized data buffer
u_int32 i;
assert(sizeof (i) <= DATA_LENGTH);
std::copy(&data[0], &data[0] + sizeof (i), reinterpret_cast<char*>(&i));
return i;
This solution works because in C++ it is permitted to access any type of object as an array of char
.
(std::copy()
is in <algorithm>
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With