Можно ли вручную вычислить смещение байта члена класса? - PullRequest
5 голосов
/ 13 июля 2011

То есть, какой стандарт компилятор использует для генерации класса? Например, предположим, что у меня есть класс C с членами x, y и z, и я хочу узнать смещение z в этом классе. Могу ли я просто сложить размеры типов данных других членов, как для структуры?

Ответы [ 7 ]

8 голосов
/ 13 июля 2011

Нет Вы не можете.
Компиляторы могут свободно выравнивать элементы по своему выбору. Это подробности реализации компиляторов.

Если вы работаете с POD , тогда вы можете использовать макрос offsetof .

Но если вы работаете с Non-POD , то, я полагаю, не будет никакого портативного метода для этого.

4 голосов
/ 13 июля 2011

Вы можете сделать это программно, как это в методе класса.Не универсальный, но работает.

offset = (unsigned char*)&(this->z) - (unsigned char*)this;

Полный рабочий пример

#include <iostream>

class C
{
public:
    int x;
    char y;
    int z;
    size_t offset() const
    {
        return (unsigned char*)&(this->z) - (unsigned char*)this;
    }
};

int main()
{
    C c;
    std::cerr << "Offset(cast): " << c.offset() << "\n";
}
2 голосов
/ 13 июля 2011

Вы можете сделать это, рассчитав смещение, используя образец объекта.(см. ответ @ bert-jan или @ sodved).

Однако это опасно! Вы не можете рассматривать классы и структуры c ++ как обычные структуры, которые вы себе представляете.

Проблема в том, что для любого заданного вами указателя на объект смещение может быть другим!

Почему?из-за подклассов и множественного наследования дополнительные данные могут быть помещены в класс перед обычными членами структуры.Количество данных может отличаться в зависимости от каждого подкласса вашего класса.


См. Этот вопрос: Почему вы не можете использовать offsetof на структурах, отличных от POD в C ++? для получения дополнительной информацииподробности.

1 голос
/ 17 ноября 2012

вы можете использовать &(class_name::member_name), чтобы получить смещение.

0 голосов
/ 13 июля 2011

Определенно не по стандарту.Существуют специальные решения для компиляторов, которые могут помочь вам сделать вывод об этом.

У Microsoft есть это:

#pragma pack(push,1)
struct Foo {
  uint8 a;
  uint32 b;
};
#pragma pack(pop)

Я могу передать (только по слухам), что GCC такжеподдерживает это с расширением.

0 голосов
/ 13 июля 2011
    #define _OFFSET(p_type, p_member) (size_t)(&((p_type *)NULL)->p_member)

    struct a
   {
       int a, b;
   };

   cout << _OFFSET(struct a, b); // output is your offset
0 голосов
/ 13 июля 2011
...