2

I wrote about this problem in other posts. Although this is not the case.

GCC compiler version: 4.8.3 (for ARM)

Code excerpt:

uint8_t data[4] __attribute__ ((aligned (8))) = {1,2,3,4};

int main()
{
    uint32_t p = 0;
    p = (uint32_t)&data[0];
    p = (uint32_t)&data[1];
    p = (uint32_t)&data[2];
    p = (uint32_t)&data[3];
}

Please note that data is outside any function, so it is NOT allocated in the stack.

The result I am seeing (when debugging) for p is: 536870912, 536870913, 536870914, 536870915;

I am expecting something like this: 536870912, 536870920, 536870928, 536870936

Any help would be much appreciated.

Hairi
  • 2,253
  • 18
  • 40

3 Answers3

2

You are telling the compiler to align the array on an 8-byte boundary. Not each of the members. Simple answer is - You cannot do it with a scalar datatype, as the compiler is not allowed to put any padding between array elements (after all, *x++ as a pointer to uint8_t should still increment the pointer only by 1).

Something like

struct alignas(8) AL_BYTE{
   uint8_t theByte;
}
struct AL_BYTE data[4] __attribute__ ((aligned (8))) = {{.theByte=1},....

should achieve what you want.

tofro
  • 4,966
  • 11
  • 29
0

I bet aligned (..) aligns an entire array instead of each item separately.

As far as I know the standard forbids any additional padding between array elements (size of array == size of each item * amount of items).

If you want each element to be aligned by 8-byte boundary, you need your elements to be 8 bytes large.

Possible solutions (combine them with __attribute__ ((aligned (8)))):

  • An array of structs (struct {uint64_t byte, padding[7];};).
  • An array of uint64_t (then you will need to make sure that you use only the lowest byte of each number). This will only work properly on lil-endian platforms.
  • An array of uint8_t, 8 times larger than you actually need (again, you need to make sure that you use only bytes that you need).
HolyBlackCat
  • 45,832
  • 5
  • 81
  • 134
-1

A possible solution is to typedef char with alignment into a new type, then make an array out of the new type, which unfortunately does not work in GCC, demoed here

typedef char AlignedChar __attribute__ ((aligned (8)));

AlignedChar test[16]={};

//prog.c:4:1: error: alignment of array elements is greater than element size

Some details can be found among the comments in this question

But this works for clang. clang's behavior is to change the sizeof the new type to include the alignment, which is desired.

I considered this a GCC bug and filed a bug report 70407.

Community
  • 1
  • 1
user3528438
  • 2,506
  • 2
  • 16
  • 36
  • I am really not sure whether I like the idea of allowing a `typedef` to change the alignment of a simple data type in an array. Note I am not saying it's right or wrong, I am not familiar with the standards enough. User-defined data types like structs, I'm generally fine with, but scalar data types like in your example - That gives me an itch..... – tofro Mar 28 '16 at 12:22
  • One of the itches is the meaning of `sizeof`as "size used" vs. "size valid" for scalars. – tofro Mar 28 '16 at 13:03
  • @tofro According to the standard `sizeof` is indeed "size used". – user3528438 Mar 28 '16 at 15:10