Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interpret binary data as an integer?

Tags:

c++

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!

like image 696
StackedCrooked Avatar asked May 27 '10 15:05

StackedCrooked


People also ask

How do you represent integers in binary?

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.

What is the difference between integer and binary?

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).

What is integer in data representation?

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.


1 Answers

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>)

like image 138
James McNellis Avatar answered Nov 06 '22 23:11

James McNellis