Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Специальные поля в заголовках структур и классов


Автор: marcusmae 18.8.2008, 13:42
Здравствуйте,

В каких случаях в заголовке структур и классов перед данными располагаются специальные поля типа указателя на таблицу виртуальных функций? Интересует вообще всё, что может находиться между адресом экземпляра и адресом верхнего поля. Если случаев немного, то перечислите, пожалуйста, кратко и / если нет подскажите, где почитать. Кстати, стандарт на этот счёт что-то определяет?..

Спасибо.

Автор: bsa 18.8.2008, 14:25
Думаю, что если это и есть, то компиляторозависимо.

Автор: Alek86 18.8.2008, 14:51
стандарт говорит, что это не определено
и размер класса и расположение данных внутри него - на совести компилятора

Автор: marcusmae 18.8.2008, 15:10
Цитата(Alek86 @  18.8.2008,  14:51 Найти цитируемый пост)
стандарт говорит, что это не определенои размер класса и расположение данных внутри него - на совести компилятора


если под рукой, можно цитату?..

Автор: UnrealMan 18.8.2008, 15:56
Цитата(marcusmae @  18.8.2008,  16:10 Найти цитируемый пост)
если под рукой, можно цитату?.. 

Правильно сделал, что спросил: тебе нагло наврали (тут такое нередко бывает smile)

Цитата(9.2 Class members)
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated
so that later members have higher addresses within a class object. The order of allocation of nonstatic
data members separated by an access-specifier is unspecified (11.1).

Цитата(9.2 Class members)
A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve appropriate alignment. ]

Автор: Daevaorn 18.8.2008, 16:00
И где наврали?

Автор: SABROG 18.8.2008, 16:08
Такую фигню накатал.

Код

#include <iostream>
using namespace std;

class test
{
public:
    test()
    {
        data = -1;
        data = 1;
        data2 = 2;
    };
    ~test(){};
    int data;
    int data2;
    unsigned char data3;
};
class test2
{
public:
    test2()
    {
        data = -1;
        data = 1;
        data2 = 2;
    };
    ~test2(){};
    int data;
    int data2;
    unsigned char data3;
};

int main(int argc, char *argv[])
{
    test *pt = new test;
    test2 *pt2 = new test2;
    test pt3;
    test2 pt4; 
    cout << "main addr: " << (int *)&main << endl;
    cout << "base addr test: " << pt << "\ndata addr: " << (int *)&pt->data << "\ndata2 addr: " << (int *)&pt->data2 << "\ndata3 addr: " << (int *)&pt->data3 << endl;
    cout << "base addr test2: " << pt2 << "\ndata addr: " << (int *)&pt2->data << "\ndata2 addr: " << (int *)&pt2->data2 << "\ndata3 addr: " << (int *)&pt2->data3 << endl;
    cout << "base addr local test2: " << (int *)&pt4 << "\ndata addr: " << (int *)&pt4.data << "\ndata2 addr: " << (int *)&pt4.data2 << "\ndata3 addr: " << (int *)&pt4.data3 << endl;
    cout << "base addr local test: " << (int *)&pt3 << "\ndata addr: " << (int *)&pt3.data << "\ndata2 addr: " << (int *)&pt3.data2 << "\ndata3 addr: " << (int *)&pt3.data3 << endl;
    delete pt, pt2;
    return 0;
}


Выдало:

Код

main addr: 0x4012f0
base addr test: 0x3f2450
data addr: 0x3f2450
data2 addr: 0x3f2454
data3 addr: 0x3f2458
base addr test2: 0x3f24c8
data addr: 0x3f24c8
data2 addr: 0x3f24cc
data3 addr: 0x3f24d0
base addr local test2: 0x22ff40
data addr: 0x22ff40
data2 addr: 0x22ff44
data3 addr: 0x22ff48
base addr local test: 0x22ff50
data addr: 0x22ff50
data2 addr: 0x22ff54
data3 addr: 0x22ff58


Т.е. 112 байт затерялось где-то между классами при выделении памяти через new, а в стеке все идет по-порядку. Компилятор gcc, спец. заголовков перед данными не видать. Т.е. пока адрес класса равен адресу первого члена данных.

Автор: marcusmae 18.8.2008, 16:18
UnrealMan, спасибо,

Цитата

Нестатические поля-значения не-union классов (т.е. структур и классов, да?) объявленные без intervening access-specifier размещаются в памяти таким образом, что чем ниже поле, тем выше его адрес в памяти. Порядок размещения нестатических полей-значений, разделённых intervening access-specifier неопределён. 


- что означает термин intervening access-specifier? Обычные спецификаторы доступа - private-public-protected, да? Если перевести на доступный язык, то получается, что в рамках секции с некоторым доступом все поля-значения размещаются ровно в том порядке, в каком они перечисленны в классе. Очень мило, что поля-указатели не оговариваются smile и что секции в принципе могут перемешиваться.

Второй тезис вообще пока не могу воткнуть smile 

SABROG, спасибо,

Будет гораздо интереснее, если Вы продолжите анализ, введя виртуальные функции и/или множественное наследование.

Автор: UnrealMan 18.8.2008, 16:39
Цитата(marcusmae @  18.8.2008,  17:18 Найти цитируемый пост)
Обычные спецификаторы доступа - private-public-protected, да? 

Да.

Цитата
access-specifier:
    private
    protected
    public


Цитата(marcusmae @  18.8.2008,  17:18 Найти цитируемый пост)
Если перевести на доступный язык, то получается, что в рамках секции с некоторым доступом все поля-значения размещаются ровно в том порядке, в каком они перечисленны в классе. 

Если между двумя нестатическими членами-данными не находится access-specifier, то больший адрес имеет тот, что объявлен позже. При этом между членами могут быть пустоты.

Касаемо POD-структур гарантируется, что объект такой структуры и его первый нестатический член-данное могут быть преобразованы друг в друга посредством reinterpret_cast:

Код

#include <iostream>

struct A
{
    double d;
    int i;
};

int main()
{
    A a;
    double &d = reinterpret_cast<double &>(a);
    d = 3.14;                                   // эквивалентно a.d = 3.14
    reinterpret_cast<A &>(d).i = 12;            // эквивалентно a.i = 12
    std::cout << a.d << " " << a.i << std::endl;
}

Автор: Alek86 18.8.2008, 16:55
Цитата(UnrealMan @  18.8.2008,  15:56 Найти цитируемый пост)
Правильно сделал, что спросил: тебе нагло наврали (тут такое нередко бывает )

а теперь покажи, где я наврал

я ответил, на вопрос
Цитата(marcusmae @  18.8.2008,  13:42 Найти цитируемый пост)
В каких случаях в заголовке структур и классов перед данными располагаются специальные поля типа указателя на таблицу виртуальных функций? Интересует вообще всё, что может находиться между адресом экземпляра и адресом верхнего поля.

ответ - не определено

Автор: marcusmae 18.8.2008, 17:04
Цитата(UnrealMan @  18.8.2008,  16:39 Найти цитируемый пост)
Если между двумя нестатическими членами-данными не находится access-specifier, то больший адрес имеет тот, что объявлен позже. При этом между членами могут быть пустоты.


Ну да. Именно это я и наблюдаю чаще всего.

Alek86, из цитаты следует, что порядок следования членов определён в некоторой степени. Вы сказали, что это на совести компилятора. Но это не то, что я спрашивал : иногда случаются пустоты перед первым членом - хорошо, если стандарт этого не оговаривает (а он именно не оговаривает : написано, что не определено и не оговаривается - не одно и то же), то можно ли говорить хотя бы о каких-то закономерностях?

Цитата(UnrealMan @  18.8.2008,  16:39 Найти цитируемый пост)

Код

double &d = reinterpret_cast<double &>(a);
d = 3.14;                                   // эквивалентно a.d = 3.14



- круто! А для reinterpret_cast нужен rtti?

Автор: Alek86 18.8.2008, 17:15
Цитата(marcusmae @  18.8.2008,  17:04 Найти цитируемый пост)
из цитаты следует, что порядок следования членов определён в некоторой степени.

а, точно, я и про порядок говорил
не знал... smile


Цитата(marcusmae @  18.8.2008,  17:04 Найти цитируемый пост)
можно ли говорить хотя бы о каких-то закономерностях?

имхо, лучше на этот счет вообще не париться.
делать сериализацию и не морочить себе голову smile

Автор: UnrealMan 18.8.2008, 18:47
Цитата(Alek86 @ 18.8.2008,  17:55)
Цитата(UnrealMan @  18.8.2008,  15:56 Найти цитируемый пост)
Правильно сделал, что спросил: тебе нагло наврали (тут такое нередко бывает )

а теперь покажи, где я наврал

я ответил, на вопрос
Цитата(marcusmae @  18.8.2008,  13:42 Найти цитируемый пост)
В каких случаях в заголовке структур и классов перед данными располагаются специальные поля типа указателя на таблицу виртуальных функций? Интересует вообще всё, что может находиться между адресом экземпляра и адресом верхнего поля.

ответ - не определено

Для POD-структуры гарантируется, что перед первым нестатическим членом-данным не может быть никаких неименованных пустот (см. примечание во второй приведённой мной цитате из п. 9.2 стандарта), а также что адрес её первого нестатического члена-данного совпадает с адресом её экземпляра (следствие из двух приведённый мной цитат). Это, по-твоему, можно расценивать как полное отсутвие в стандарте информации по данному топику? smile

Добавлено через 31 секунду
Цитата(marcusmae @  18.8.2008,  18:04 Найти цитируемый пост)
А для reinterpret_cast нужен rtti?

Нет.

Автор: bsa 18.8.2008, 20:03
блин. а я грешным делом подумал, что речь идет о чем-то, что находится до адреса, на который указывает указатель  smile 

Автор: Alek86 18.8.2008, 20:56
Цитата(UnrealMan @  18.8.2008,  18:47 Найти цитируемый пост)
Для POD-структуры гарантируется, что перед первым нестатическим членом-данным не может быть никаких неименованных пустот (см. примечание во второй приведённой мной цитате из п. 9.2 стандарта), а также что адрес её первого нестатического члена-данного совпадает с адресом её экземпляра (следствие из двух приведённый мной цитат). Это, по-твоему, можно расценивать как полное отсутвие в стандарте информации по данному топику?

стандарт на работе - завтра погляжу
а из 2х цитат сейчас следует только то, что reinterpret_cast обязан приводить указатель на ПОД к указателю на первое поле...

если в примечании написано то, чтоговоришь, тогда я был неправ

Автор: UnrealMan 18.8.2008, 22:33
Цитата(Alek86 @  18.8.2008,  21:56 Найти цитируемый пост)
а из 2х цитат сейчас следует только то, что reinterpret_cast обязан приводить указатель на ПОД к указателю на первое поле...

если в примечании написано то, чтоговоришь

Я ни от кого не прятал это примечание:

Цитата(UnrealMan @ 18.8.2008,  16:56)
Цитата(9.2 Class members)
A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve appropriate alignment. ]

Какие тут могут быть сомнения? smile 

Автор: MAKCim 19.8.2008, 17:19
 smile 
вот поэтому (и не только) ядра ОС на С++ и не пишут
по мотивам http://forum.vingrad.ru/forum/topic-220786.html топика
 smile 

Автор: marcusmae 19.8.2008, 17:57
MAKCim, спасибо,

Цитата(bilbobagginz @  16.7.2008,  16:02 Найти цитируемый пост)

когда я пишу на C++:
Код

class A{int a;int b;}// a потом:
A myarr[10];

в зависимости от платформы я получу совершенно разные картины памяти, чем в C:
Код

typedef struct A_t{int a;int b;} A;
A myarr[10];

т.е. в C++ sizeof(A) будет возвращать зависимые от компилятора величины (т.е. двойная зависимость), тогда как в C - всё будет зависеть только от архитектуры.


да, убедились на практике smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)