powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / why (char*) ?
8 сообщений из 8, страница 1 из 1
why (char*) ?
    #32403503
AndRUsha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый вечер!

Объясните пожалуйста в чем дело :
(смотрите сразу main)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
#include <windows.h>
#include <iostream>
using namespace std;

class Base1 {
public:
	virtual void f() { cout<< "Base1::f()" <<endl; }
};

class Base2 {
public:
	virtual void f() { cout<< "Base2::f()" <<endl; }
};

class Base3 {
public:
	virtual void f() { cout<< "Base3::f()" <<endl; }
};

class Drive : public Base1, public Base2, public Base3 {
};


#define _ATL_PACKING  1 

#define offsetofclass(base, derived) \
	((DWORD)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)


int main() {
	cout << offsetofclass(Base1, Drive) << endl;
	cout << offsetofclass(Base2, Drive) << endl;
	cout << offsetofclass(Base3, Drive) << endl;

	Drive d;

	void* pVoid = NULL;

	pVoid = (char*)&d + offsetofclass(Base1, Drive);
	(static_cast<Base1*>(pVoid))->f();

	pVoid = (char*)&d + offsetofclass(Base2, Drive);
	(static_cast<Base2*>(pVoid))->f();

	pVoid = (char*)&d + offsetofclass(Base3, Drive);
	(static_cast<Base3*>(pVoid))->f();


	return  0 ;
}


Результат следующий:

0
4
8
Base1::f()
Base2::f()
Base3::f()
Press any key to continue


Однако если изменить последние строки так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
             ...

	void* pVoid = NULL;

	pVoid = &d + offsetofclass(Base1, Drive);
	(static_cast<Base1*>(pVoid))->f();

	pVoid = &d + offsetofclass(Base2, Drive);
	(static_cast<Base2*>(pVoid))->f();

	pVoid = &d + offsetofclass(Base3, Drive);
	(static_cast<Base3*>(pVoid))->f();


	return  0 ;
}


то результат такой:

0
4
8
Base1::f()


плюс ошибка

The instruction at "0x435..." referenced memory at "0x00..00". The memory could not be read.

Благодарю за внимание!
...
Рейтинг: 0 / 0
why (char*) ?
    #32403646
dishlo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ужас...

ну если такая мясорубка пошла. то что если последовательно убрать
1 (static_cast<Base1*>(pVoid))->f();
потом
+ offsetofclass(Base1, Drive);
и посмотреть что происходит...
...
Рейтинг: 0 / 0
why (char*) ?
    #32403758
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дело в первом косте

pVoid = (char*)&d

после коста результат сразу пойдёт как укачатель на чар. То бишь
offsetofclass(Base2, Drive) - пойдёт как смещение в байтах

если же

pVoid = &d, результат пойдёт как 32битное и к указателю на голову класса Д прибабится 4-байтная дельта а не 1-байтная. Отсюда получится неправильное смещение, которое и не сможет вызвать f()

(static_cast<Base2*>(pVoid))->f(); - ошибка.
...
Рейтинг: 0 / 0
why (char*) ?
    #32409768
Cactus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Наверно, так более безопасно

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
	pVoid = (void*)(reinterpret_cast <UINT>(&d) + offsetofclass(Base1, Drive));
	(static_cast<Base1*>(pVoid))->f();

	pVoid = (void*)(reinterpret_cast <UINT>(&d) + offsetofclass(Base2, Drive));
	(static_cast<Base2*>(pVoid))->f();

	pVoid = (void*)(reinterpret_cast <UINT>(&d) + offsetofclass(Base3, Drive));
	(static_cast<Base3*>(pVoid))->f();
...
Рейтинг: 0 / 0
why (char*) ?
    #32410082
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А ты пробовал? Работает?

что &d что (void*)(reinterpret_cast <UINT>(&d)

типом результата первого слагаемого будет (void*)
...
Рейтинг: 0 / 0
why (char*) ?
    #32410534
Cactus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To CEMb
Пробовал. Работает.

Можно и так
Код: plaintext
1.
2.
	pVoid = [color=green](Drive*)[/color](reinterpret_cast <UINT>(&d) + offsetofclass(Base1, Drive));
	(static_cast<Base1*>(pVoid))->f();


сам понимаешь, по барабану.

Идея была в том, что в скобках два целых сложить и работать с результатом, как с адресом.

Мне кажется, что использование reinterpret_cast в этом контексте более безопасно, чем (char*)&d.
...
Рейтинг: 0 / 0
why (char*) ?
    #32410576
YuriAM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если к указателью прибавить хоть единицу, то он будет указывать на адрес, который являеться собственный + длина типа , на который указывает указатель.
Следовательно, в Вашем примере, чтобы попасть на очередные функции, надо прибавить не смещение адреса, а просто 1.
То есть -
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
	void* pVoid = NULL;

	pVoid = &d +  0 ;
	(static_cast<Base1*>(pVoid))->f();

	pVoid = &d +  1 ;
	(static_cast<Base2*>(pVoid))->f();

	pVoid = &d +  2 ;
	(static_cast<Base3*>(pVoid))->f();

...
Рейтинг: 0 / 0
why (char*) ?
    #32410702
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А! Всё, увидел скобку, сорри :)
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / why (char*) ?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]