Вопрос о выравнивании памяти на С++

Строка кода стоит тысячи слов:) Вот моя проблема:

/* Platform specific 16-byte alignment macro switch.
   On Visual C++ it would substitute __declspec(align(16)).
   On GCC it substitutes __attribute__((aligned (16))).
*/
#define ALIGN_16 ...

struct ALIGN_16 A {...};

A* ptr = new A;
A* ptr2 = new A[20];

assert(size_t(ptr) % 16 == 0);

for (int i=0; i<20; ++i)
    assert(size_t(ptr2+i) % 16 == 0);

assert(sizeof(A) % 16 == 0);

Можно ли ожидать, что все утверждения пройдут на платформах с поддержкой SSE? Спасибо.

ИЗМЕНИТЬ. Частичный ответ. Я провел некоторое тестирование с VS2008, GCC и ICC. MS-компилятор выполнил выравнивание ptr и ptr2, но GCC и ICC не смогли выровнять ptr2.

Ответ 1

Есть ли гарантия выравнивания возврата адреса с помощью новой операции С++?

Другими словами, вы можете использовать стандарт, чтобы оправдать свое предположение, что он должен работать, но на практике он может взорваться в вашем лице.

Visual С++ 6 не выровнял doubles, назначенный через new правильно, так что вы идете.

Ответ 2

С++ 0x предоставляет новую конструкцию (в [meta.type.synop] 20.7.6.6 другие преобразования):

std::aligned_storage<Length, Alignment>

который, как я помню, гарантированно всегда правильно выровнен.

Второй параметр является необязательным, и по умолчанию используется максимально возможное требование (чтобы всегда было безопасно не уточнять его, но вы можете упаковать свои типы более компактно, если захотите попробовать).

Помимо ошибок, компилятор обязан соблюдать это требование. Если у вас нет С++ 0x, это можно найти в пространстве имен tr1 или на Boost.

Вы единственный, кто может проверить, что ваш конкретный компилятор выполняет этот запрос:)

Примечание: в gcc-4.3.2 он реализован как:

template<std::size_t _Len, std::size_t _Align = /**/>
struct aligned_storage
{
  union type
  {
    unsigned char __data[_Len];
    struct __attribute__((__aligned__((_Align)))) { } __align;
  };
};