Предлагаемый вами вариант не приведет к выравниванию всей структуры на 8-байтовой (64-битной) границе, которую вы упоминаете в качестве требования из RFC2553.
В общем, структура принимает строжайшее выравнивание, требуемое любым из ее членов. Поскольку sa_family_t
- это, вероятно, u16_t
, для которого требуется только 2-байтовое выравнивание, а для массива char требуется не более 1-байтового выравнивания, предлагаемый вами вариант потребует только 2-байтового выравнивания. (Вполне вероятно, что компилятор в любом случае даст ему как минимум 4- и, возможно, 8-байтовое выравнивание, но вы не можете быть уверены.)
Стиль фактического определения - это попытка убедиться, что каждый байт в структуре является частью некоторого именованного поля, т. Е. Что компилятор не вставляет какие-либо отступы между полями. Это необходимо (в некотором роде), чтобы _SS_PAD2SIZE
имел значение, которое можно вычислить с точки зрения размеров всех других членов.
Однако я нахожу это определение довольно сложным. Я уверен, что следующее работает так же хорошо, и его немного легче понять:
struct sockaddr_storage {
union {
sa_family_t u_family;
uint64_t u_pad[_SS_MAXSIZE / sizeof(uint64_t)];
} __ss_u;
# define __ss_family __ss_u.u_family
};
Здесь объединение получает требования к выравниванию своего наиболее строго выровненного элемента, который затем распространяется на включающую структуру. Обратите внимание, что в этой версии у меня есть только одно обязательное поле (хотя оно и похоронено в объединении) и один массив заполнения, который является точным размером, который я хочу, чтобы была вся структура. Единственная немного сложная часть - это макроопределение __ss_family
. Возможно, что макро-трюк не полностью соответствует требованиям в RFC, но будет немного (если таковые имеются) способов заметить разницу.