Re: [問題] 關於Class指標的觀念
看板C_and_CPP (C/C++)作者descent (「雄辯是銀,沉默是金」)時間11年前 (2013/08/27 20:48)推噓2(2推 0噓 21→)留言23則, 7人參與討論串4/19 (看更多)
※ 引述《littleshan (我要加入劍道社!)》之銘言:
: → GNUGCC:看來各位好像不太能理解其中的道理,各位要記得,記憶體位址 08/26 20:02
: → GNUGCC:永遠都是「無號數整數型態」,float 與 double 是屬於實數型 08/26 20:03
: struct A {
: void func() {}
: };
: void (A::*p) = &A::func;
: cout << (unsigned long)p << endl;
: VC++ 2012 編譯結果:
: hello.cpp(12) : error C2440: '型別轉換' : 無法由 'void (__thiscall
: main::A::* )(void)' 轉換為 'unsigned long'
: 沒有可以進行此轉換的內容
: 啊不是說都無號整數?為什麼轉不過去啊?
: 不然轉指標好了
: cout << (int*)p << endl;
終於知道在討論什麼了。
指標就是指標, 我看不懂 (int*)p 要預期得到什麼?
因為應該不會有人想要看 A::func() 前 4 byte (32bit environment),
這並沒有什麼意義。而且語法也不支援這樣的用法, 我還蠻驚訝的,
我一直以為 reinterpret_cast 什麼都能轉, 結果踢到鐵板。
不過可以轉 void*, 再來就隨便人轉了。
但如果要得到 p (A::func() 的位址)的位址的話,
可以使用這樣的方法:
#include <cstdio>
using namespace std;
int main()
{
struct A {
void func() {}
};
void (A::*p)() = &A::func;
unsigned int addr = *((unsigned int*)&p);
#if 1
printf("p: %p\n", p);
printf("addr: %x\n", addr);
#endif
return 0;
}
objdump
0804856e <_ZZ4mainEN1A4funcEv>:
804856e: 55 push %ebp
804856f: 89 e5 mov %esp,%ebp
8048571: 5d pop %ebp
8048572: c3 ret
descent@debian-vm:tmp$ c++filt _ZZ4mainEN1A4funcEv
main::A::func()
descent@debian-vm:tmp$ ./c
p: 0x804856e
addr: 804856e
env:
debian/x86 32 bit 環境
我猜 printf 應該也是類似的作法, 才能正確印出 A::func() address。
: VC++ 2012 編譯結果:
: hello.cpp(12) : error C2440: '型別轉換' : 無法由 'void (__thiscall
: main::A::* )(void)' 轉換為 'int*'
: 沒有可以進行此轉換的內容
: 啊不是說實作上可行嗎?
: 我試了一堆 compiler 都不給我過啊!
: 好啦我還沒測 VC6,搞不好這個特異的 compiler 還真的能編
: → a27417332:還蠻好奇有那些機器的記憶體位址是違反無號正整數? 08/26 21:12
: → a27417332:總覺得目前的眼界還是太小XDlll感覺有好多不可思議的事 08/26 21:13
這個我還是沒搞懂。
: 上面那個例子就是了
: 不用什麼特別的機器
: 你現在在用的電腦也一樣編不過
: → GNUGCC:記憶體位址對任何機器來說都是屬於連續的位址編號,並不會有 08/26 21:24
: → GNUGCC:所謂的違反問題,就好像住家地址不可能以自已的姓名代表一樣 08/26 21:25
: 還連續編號勒
: 告訴我上面的 p 到底是幾號啊!
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 111.184.185.55
※ 編輯: descent 來自: 111.184.185.55 (08/27 21:00)
→
08/27 21:04, , 1F
08/27 21:04, 1F
→
08/27 21:04, , 2F
08/27 21:04, 2F
→
08/27 21:59, , 3F
08/27 21:59, 3F
→
08/27 21:59, , 4F
08/27 21:59, 4F
→
08/27 21:59, , 5F
08/27 21:59, 5F
→
08/27 22:08, , 6F
08/27 22:08, 6F
→
08/27 22:09, , 7F
08/27 22:09, 7F
→
08/27 22:10, , 8F
08/27 22:10, 8F
→
08/27 22:11, , 9F
08/27 22:11, 9F
推
08/27 22:14, , 10F
08/27 22:14, 10F
→
08/27 22:26, , 11F
08/27 22:26, 11F
#include <cstdio>
using namespace std;
struct A {
void func()
{
printf("123\n");
}
};
typedef void (A::*MF)();
int main()
{
void (A::*p)() = &A::func;
A a;
(a.*p)();
unsigned int addr = *((unsigned int*)&p);
(*(void(*)())(addr) )();
#if 1
printf("p: %p\n", p);
printf("addr: %x\n", addr);
#endif
return 0;
}
執行結果:
descent@debian-vm:tmp$ ./c
123
123
p: 0x804861a
addr: 804861a
是可以執行的。
※ 編輯: descent 來自: 111.184.185.55 (08/27 22:46)
→
08/27 22:48, , 12F
08/27 22:48, 12F
→
08/27 22:51, , 13F
08/27 22:51, 13F
→
08/27 22:51, , 14F
08/27 22:51, 14F
→
08/27 22:52, , 15F
08/27 22:52, 15F
→
08/27 22:53, , 16F
08/27 22:53, 16F
→
08/27 22:54, , 17F
08/27 22:54, 17F
→
08/27 22:54, , 18F
08/27 22:54, 18F
→
08/27 22:55, , 19F
08/27 22:55, 19F
推
08/27 22:59, , 20F
08/27 22:59, 20F
→
08/27 23:00, , 21F
08/27 23:00, 21F
→
08/27 23:00, , 22F
08/27 23:00, 22F
→
08/27 23:06, , 23F
08/27 23:06, 23F
※ 編輯: descent 來自: 111.184.185.55 (08/27 23:10)
討論串 (同標題文章)
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章