struct — C ++ Non-Pod начальный адрес

В C первый элемент структуры имеет тот же адрес, что и сама структура. То же самое относится и к структурам без POD в C ++, если первым элементом является POD?

Например, учитывая этот код:

struct bar
{
struct bar *p1, *p2;
unsigned char h;
}

struct foo
{
struct bar node;
int a;

private:
int x;
};

int main(void)
{
struct foo A;
struct bar *ptr;

ptr = &A.node;

struct foo *n = ((struct foo*)((char*)(ptr)-(unsigned long)(&((struct foo*)0)->node)));

return 0;
}

Я получаю «недопустимый доступ к нестатическому члену данных ‘foo :: node’ объекта NULL … возможно, смещение макроса смещения использовалось неправильно».

У меня такой вопрос — могу ли я предположить, что «узел» находится в начале foo (тот же адрес), даже если это не-POD структура?

Если да, я могу просто использовать реинтерпретацию и не получаю предупреждения:

struct foo *o = reinterpret_cast<struct foo*>(ptr);

Итак, если структура C ++ начинается с общедоступных данных POD, будет ли первый элемент иметь адрес объекта в соответствии со стандартом?

Спасибо

—редактировать—
Можно ли предположить, что в классе без виртуальных методов или суперкласса (адрес переменной первого члена) == this? был указан в качестве возможного ответа. В нем упоминается «Нестатические члены данных (не объединяющего) класса, объявленные без промежуточного спецификатора доступа, распределяются таким образом, чтобы более поздние члены имели более высокие адреса в объекте класса». Это на самом деле не относится к первому элементу или нет в моем случае это тот же адрес, что и сам объект.

Я думаю, что поскольку стандарт ничего не говорит об этом, я не могу предположить, что это так. Мне может понадобиться изменить объекты в конце структуры на указатели и по мере необходимости распределить их.

1

Решение

Стандарт говорит в [class.mem] / 19

Если объект класса стандартной компоновки имеет какие-либо нестатические элементы данных, его адрес совпадает с адресом его первого нестатического члена данных. В противном случае его адрес совпадает с адресом его первого подобъекта базового класса (если есть). [Примечание: поэтому в структуре стандартного макета может быть безымянный отступ
объект, но не в его начале, так как это необходимо для достижения соответствующего выравнивания. —Конечная записка]

Так что, если класс стандартная компоновка который не соответствует стандарту, гарантирует, что адрес первого члена является адресом класса. В вашем случае говорится, что это адрес первого базового класса. Поскольку у вас нет базового объекта, это означает, что первый член разделяет адрес объекта, поскольку в начале объекта никогда не может быть заполнения. Это означает, что адрес foo это адрес его bar член и с тех пор bar является стандартным классом макета, это также будет адрес p1,

Обратите внимание, что попытка получить любого члена после первого члена является неопределенным поведением. Типы классов (включая struct) разрешено иметь отступы между любыми членами класса для выравнивания. Это означает, что вы никогда не знаете, где именно находятся другие участники по отношению к первому участнику.

1

Другие решения

Согласно Славе, поскольку виртуальные таблицы могут быть частью структуры, поэтому короткий ответ — нет. Теперь vtables не является частью стандарта. Это всего лишь механизм реализации виртуальной вещи и, таким образом, достижения полиморфизма. Ответ до сих пор нет по всем практическим причинам.

Пожалуйста, смотрите следующий код:

#include <iostream>

using namespace std;

struct bar
{
struct bar *p1, *p2;
unsigned char h;
};

struct foo
{
struct bar node;
int a;

private:
int x;
};

int main(void)
{
struct foo A;
struct bar *ptr;

A.node.p1 = new bar();
A.node.p2 = new bar();
ptr = &A.node;

struct foo *n = ((struct foo*)((char*)(ptr)-(unsigned long)(&((struct foo*)0)->node)));
cout << n->a << endl;

return 0;
}

Код скомпилирован с g++ -Wall -Werror -pedantic -std=c++14 test.cpp, Проблема в том, что я думаю, что вы не выделяете память для p1 а также p2,

-4

По вопросам рекламы [email protected]