По этой теме уже был вопрос (в частности, Как получить адрес некоторого элемента структуры в массиве структур).

У меня такой вопрос: когда мы используем struct для описания аппаратного устройства, поэтому каждый член структуры будет соответствовать некоторым регистрам аппаратного устройства - как мы можем быть уверены, что каждый член структуры правильно отображается на каждый регистр аппаратного обеспечения?

ABI компилятора диктует выравнивание членов, пользователь также может совершить некоторую ошибку - и единственный способ убедиться, что сопоставление выполнено правильно, - это проверить во время выполнения. Файл карты (по крайней мере, для GNU ld) не дает никаких сведений о размещении элементов структуры.

Будет ли способ узнать во время компиляции или компоновки, где расположены все элементы структуры?

0
Pierre G. 9 Ноя 2017 в 16:09

1 ответ

Лучший ответ

Вы можете использовать offsetof вместе с static_assert.

Например, совершенно произвольный

#include <cstddef>
struct iom {     // off,len
  uint32_t rx;   // +0,4
  uint32_t tx;   // +4,4
  uint64_t clk;  // +8,8
  uint16_t irq;  // +16,2
};
static_assert(offsetof(iom,rx)==0);
static_assert(offsetof(iom,tx)==4);
static_assert(offsetof(iom,clk)==8);
static_assert(offsetof(iom,irq)==16);

Если static_assert не работает, например, потому что ваш компилятор выравнивает члены по 64-битным границам, вам нужен специальный способ компилятора для изменения выравнивания и заполнения. Например, с gcc,

    } __attribute__((packed));

В конце определения структуры.


NB. Я ответил за C ++ 17.

C ++ 11 или 14 или C11 требуют сообщения об ошибке в качестве второго аргумента static_assert, хотя вы можете обернуть все это в макрос, чтобы составить для вас удобную строку.

Макрос offsetof также работает в Си.

3
Useless 9 Ноя 2017 в 17:44