Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting UNALIGNED MSVC specific code to portable C++ code?

I'm trying to convert some C++ Code that is written for MSVC so it can run on GCC or Clang.

The offending keyword is

UNALIGNED

pData is LPCBYTE

An example of the code is:

 INT8 some8Value =  *(UNALIGNED INT8 *)&(pData[offset]);

INT64 some64Value = *(UNALIGNED INT64 *)&(pData[offset]);

I think I understand what logically this code wants to do, it wants to read in the 1 byte from the pointer pointing to pData + offset.

The second one is saying read 8 bytes from the pData + offset pointer.

The confusing part is why is the first one UNALIGNED. I thought reading 1 byte is always aligned.

Or am I misreading the code somehow?

Is the cross platform way of doing this the following:

INT8 part1 = pData[offset];
INT8 part2 = pData[offset + 1];
...

And then combine the 8 parts (for example) in the INT64 case?

like image 816
halivingston Avatar asked Feb 12 '26 01:02

halivingston


2 Answers

This is a macro that equates to __unaligned when compiling for Itanium processors, and to nothing for all other CPU's. From MSDN (@ https://msdn.microsoft.com/en-us/library/ms177389.aspx):

When you declare a pointer with the __unaligned modifier, the compiler assumes that the pointer addresses data that is not aligned. Consequently, for an application that targets an Itanium Processor Family (IPF) computer, the compiler generates code that reads the unaligned data one byte at a time.

In your case simply equates it to nothing in a header:

#define UNALIGNED

Or, if you like, remove it from each place in the code.

EDIT: On ARM processors specifically can be used the qualifier __packed to specify for unaligned data, that existo for GCC as __attribute__ ((__packed__)), but doesn't exist for MSVC. For the latter the only choice is #pragma pack(1) which effect however should be limited to structures.
More info on SO answer Visual C++ equivalent of GCC's __attribute__ ((__packed__)).

like image 167
Frankie_C Avatar answered Feb 13 '26 14:02

Frankie_C


In GCC you can use aligned(1) attribute:

typedef int64_t __attribute__(( aligned(1) )) UNALIGNED_INT64;

UNALIGNED_INT64 unalignedPtr = pData + offset;
INT64 some64Value = *unalignedPtr;

from the GCC documentation:

When used on a struct, or struct member, the aligned attribute can only increase the alignment; in order to decrease it, the packed attribute must be specified as well. When used as part of a typedef, the aligned attribute can both increase and decrease alignment, and specifying the packed attribute generates a warning.

Read more here: Why does this alignment attribute have to be specified in a typedef?

like image 35
gabonator Avatar answered Feb 13 '26 16:02

gabonator