Итак, у меня есть следующий свернутый код C11, который определяет структуру, содержащую uint16_t (что означает, что структура должна быть выровнена с 2 байтами), и я хочу, чтобы буфер char указывал на эту структуру.
С предупреждениями все поднялось, глаг справедливо жаловался, что требования к выравниванию структуры не выполняются. Поэтому я добавил спецификатор C11 alignas
в буфер, чтобы убедиться, что буфер достаточно выровнен, но это не заслонило clang.
Мой вопрос: я делаю что-то не так с alignas
? Или это просто, что диагностика -Wcast-align проверяет только тип аргументов, а также не на ручное заданное выравнивание? (Я понимаю, что могу просто нажать на void*
, чтобы отключить диагностику, но поскольку этот фрагмент кода должен быть переносимым, я не хочу, чтобы он прошел шаг по диагностике, если я не уверен, что это ложный позитив.)
#include <stdint.h>
#include <stdalign.h>
struct foo {
uint16_t field1;
};
int main(void) {
alignas(struct foo) char buffer[122] = {0};
struct foo *foo = (struct foo*)buffer;
return foo->field1;
}
Параметры компилятора и сообщение об ошибке:
$ clang -ggdb -O3 foo.c -Weverything -Werror -Wno-c++98-compat -Wno-c11-extensions
foo.c:11:23: error: cast from 'char *' to 'struct foo *' increases required alignment from 1 to 2 [-Werror,-Wcast-align]
struct foo *foo = (struct foo*)buffer;
^~~~~~~~~~~~~~~~~~~~~~~~~
Версия компилятора:
$ clang -v
clang version 3.5.1 (tags/RELEASE_351/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
Selected GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4
Update: Предупреждение не возникает, когда я перемещаю буфер и его выравнивание в структуру. Я интерпретирую это как намек на то, что clang действительно смотрит только на типы этого предупреждения.
#include <stdint.h>
#include <stdalign.h>
struct foo {
uint16_t field1;
};
struct bar {
alignas(struct foo) char buffer[122];
};
int main(void) {
struct bar bar = {{0}};
struct foo *foo = (struct foo*)&bar;
return foo->field1;
}