Я вижу, что в C ++ 17 введены выровненные новые выражения с std::align_val_t
для объектов, требующих большего выравнивания, чем предусмотрено в new
.Это здорово, но заставило меня задуматься:
Почему выравнивание указателя не является частью типов указателя?
Например:
long foo(long *x) {
return *x; // here, the compiler do an aligned load
// correct as (long*) is expected to be aligned
}
Будетпредположим, что указатель выровнен на 64 бита (на моей машине).Но компилятор не предупредит меня, если я сделаю следующее:
long bar(char *x) {
return foo((long*) x); // here, the compiler do an aligned load, risky!
}
long pop(char *z) {
return bar(z + 1); // here, the compiler do an aligned load too!
}
Мне удалось получить предупреждение, передав указатель на поле из упакованной структуры:
struct ugly {
char x;
long y;
} __attribute__((packed));
long kun(ugly *a) {
return a->y; // here, the compiler do an unaligned load, correct!
}
long zip(ugly *a) {
return foo(&a->y); // here, the compiler do an aligned load, incorrect!
// but warns me about it.
}
Нопочему это не ошибка, сродни const_cast
?
Что говорит стандарт в отношении выравнивания?
Все ли компиляторы делают неверные предположения илиЭто неопределенное / определенное реализацией поведение, чтобы дать невыровненный указатель на функцию?
Вы можете увидеть их в действии здесь: https://godbolt.org/g/9ddbiq
Редактировать : Исправлен фрагмент кодаи предоставил ссылку на Годблот.