看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《descent (「雄辯是銀,沉默是金」)》之銘言: : 但如果要得到 p (A::func() 的位址)的位址的話, : 可以使用這樣的方法: [deleted] : 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。 咈咈咈~~果然有人踩進來了 不過實驗精神可佳 應該賞予坐墊一枚 member function pointer 的陷阱在於這個指標並不能視為一個整數 (講N次了) 我們來看一個應該會讓許多人驚訝的例子 #include <cstdio> struct A { virtual void func(); }; void A::func() {...} int main() { void (A::*p)() = &A::func; printf("addr: %p", p); return 0; } objdump + c++filt: 000000000040094c <A::func()>: 執行結果 (Debian x64 + gcc 4.7.3): addr: 0x1 所以 A::func 的位址是 0x0000000000000001 這好像不太對 XDDDD * * * 另一個提示 struct A { void func(); }; int main() { cout << "sizeof(int*) = "<<sizeof(int*) << endl; cout << "sizeof(&A::func) = " << sizeof(&A::func) << endl; return 0; } 在我的電腦上 (Debian x64 + gcc 4.7.3) 是這樣: sizeof(int*) = 8 sizeof(&A::func) = 16 在 gcc 上,member function pointer 的大小是一般指標的兩倍呢!好開心啊 XD 事實上不同的 compiler 有非常不一樣的實作方法 有的實作和一般指標一樣大,而有的甚至占用四倍或五倍大小! 當然,你不能把 member function pointer 當作一個整數來看 因為除了函式的位址,它還必需儲存一些額外的資訊 才能正確處理 virtual function 與多重繼承 有興趣的可以看看這篇文章 http://goo.gl/2Uc2f 所以各位應該可以理解為什麼 &A::func 不能轉成 int* 這根本是兩個世界的東西 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 202.39.238.242
adxis:未看先猜 fast delegate :p 08/27 22:27
Feis:我覺得小善心機有點重.... 08/27 22:27
littleshan:我前面就好心提醒過!直接當普通指標印出來是錯的! 08/27 22:31
suhorng:大家快來寫cppgm 08/27 22:31
Feis:不過 G 大的厲害就是會說 "那還是無號正整數阿" 不就是0跟1 08/27 22:42
descent:這是 virtual 才會發生的事情吧, 不用 virtual 08/27 22:44
descent:應該不會這樣 08/27 22:44
suhorng:@descent: 可是第二個沒有virtual耶? 08/27 22:46
GNUGCC:F 大大,我說的 0 與 1 跟「正整數」是無關連的,而且我也說 08/27 22:47
GNUGCC:「它會轉呼叫輸出 BOOL 型態數值」的函式,對吧? 08/27 22:47
GNUGCC:我不知道 F 大大去扭曲我說的話的用意何在? 08/27 22:48
Feis:我扭曲什麼阿? 你就搞錯了. 而且我說的是你把東西都當整數 08/27 22:49
descent:virtual 比較麻煩, 要先去對付 virtual table 08/27 22:49
Feis:你就搞錯了亂猜呼叫輸出 bool .現在我說整數是你把 08/27 22:50
Feis:bit representation 都當做整數用. 08/27 22:50
Feis:忽略型態的意涵 08/27 22:50
GNUGCC:你說我把東西都當整數,這句話就是在扭曲了. 08/27 22:51
Feis:喔. 那記憶體位址為什麼是無號正整數? 08/27 22:51
Feis:他不就是一堆 00001110101010 嗎 08/27 22:52
GNUGCC:我前面說了那麼多,沒想到您還是不明白 08/27 22:53
Feis:對 真是蠻難明白的. 你都是影片是整數了. 我能說什麼 08/27 22:54
GNUGCC:我很好奇的是,討論記憶體的問題為何要跳 Tone 到檔案上呢? 08/27 22:56
Feis:因為你就愛扯阿. 什麼是無號正整數. 你有想過他意涵嗎 08/27 22:56
Feis:難道浮點數就不是無號正整數? 為什麼? 08/27 22:56
GNUGCC:這樣偏離討論主題不知道您的用意何在? 08/27 22:56
GNUGCC:那就換您說說看您的觀點如何? 08/27 23:00
Feis:哪個觀點? 我都說了指標不等同無號正整數大概有數十次~ 08/27 23:05
Feis:然後我發現你對"無號正整數"有些跟我不一樣的認知 08/27 23:08
Feis:所以我才跟你討論這個~ 08/27 23:08
GNUGCC:那請問「指標不等同無號正整數」的觀點為何? 08/27 23:16
littleshan:我這篇文章不就在講成員函式指標不能當整數? 08/27 23:19
Feis:因為他叫指標不叫無號正整數阿? 這觀點如何? 08/27 23:19
littleshan:還是說你覺得 &A::func 其實是個 128-bit 超大整數 08/27 23:20
Feis:littleshan: 我就怕這個... (躲) 08/27 23:20
GNUGCC:天啊!原來您的理解是在於它的「型態」,而不是它的特性... 08/27 23:21
GNUGCC:所以我在前才會說您的誤會可深了...我來從沒有說它是「無號 08/27 23:22
GNUGCC:正整數型態」,沒想到您的理解跟我的不同,我終於知道了. 08/27 23:22
azureblaze:請問哪項符合「無號非有號」的特性 08/27 23:24
johnny94:GNUGCC 你要不要自己回一篇告訴大家你想說啥 08/27 23:30
johnny94:不然一直說別人誤解你,也不知道到底是怎麼一回事 08/27 23:30
Arton0306:G大你前面說 用強制轉型 指標變數可以指向任何型態的物 08/27 23:37
Arton0306:件 因為你說是"任何" 所以L大舉了一個反例 08/27 23:37
Arton0306:所以你的敘述是錯的 這沒有什麼好爭的吧 08/27 23:37
GNUGCC:L 大的例子是因為他的方法用錯了,至於怎麼用請看前面記錄 08/27 23:43
GNUGCC:吧. 08/27 23:44
xatier:GCC 大大要不要看一下我貼的東西... 沒人理我 QQ 08/27 23:45
Feis:別難過. 你貼的我們知道阿. G大考慮的更深層~ 08/27 23:49
littleshan:『記憶體位址永遠都是「無號數整數型態」』 08/28 00:00
littleshan:8/26 20:02 的推文,你被盜帳號嗎? 08/28 00:00
LPH66:是說 xatier 提的東西我在附近某篇文裡提到過 (茶) 08/28 00:18
xatier:看來 GCC 大大正在陷入深層思考中,我們耐心等待(? 08/28 00:29
purpose:傳遞這成員函式指標還蠻費工的,看完這篇討論,比較懂了 08/28 00:33
purpose:剛測試在 VC 下,如果多重繼承兩個類別,用類別一的成員 08/28 00:34
purpose:函式指標時,參數傳遞就送物件位址,跟偏移值,比如 0 08/28 00:35
purpose:用類別二的成員函式指標時,偏移值可能就變 8,所以兩者 08/28 00:35
purpose:最終可以得到不同位址的 this 指標 08/28 00:36
azureblaze:還會有另外一個值是紀錄virtual inheritance用的 08/28 00:46
azureblaze:至於struct{void*;int;int}有什麼uint特性就不知道了 08/28 00:48
Fenikso:反正所有東西都是無號正整數 連實數也是(?) 08/28 00:54
GNUGCC:L 大,我想您大概沒看懂這句話的意思,我說的「記憶體位址永 08/28 22:05
GNUGCC:遠都是無號整數型態」跟程式語言使用的資料型態無相關,請不 08/28 22:08
GNUGCC:要移花接木. 08/28 22:08
LPH66:所以這一大串推文都在請你說說你口中的「無號整數型態」 08/29 00:36
LPH66:到底是指稱什麼樣子的特性 不然在我們完全不了解你這個名詞 08/29 00:37
LPH66:的狀況下根本無從討論起 08/29 00:37
GNUGCC:LPH66 大大的問題很好,會問到「什麼樣子的特性」,總比某些 08/29 20:21
GNUGCC:人刻意模糊討論主題. 08/29 20:22
GNUGCC:我之前所說的「記憶體位址永遠都是無號整數型態」,是指記憶 08/29 20:23
GNUGCC:體位址「編號」的特性,例如 1 條 8 G 記憶體,它的編號會從 08/29 20:25
GNUGCC:0 ~ FFFFFFFFFFFFFFFF,這個也就是它的使用範圍,從這個數字 08/29 20:28
GNUGCC:的特性來看它就是一個無負號的「正整數」,至於作業系統要怎 08/29 20:29
GNUGCC:麼使用它完全根據作業系統特性決定實際能使用的範圍,但不管 08/29 20:30
GNUGCC:使用範圍是多少,它最終都還是一個整數而已,那些位址編號就 08/29 20:31
GNUGCC:是我們所熟知的「記憶體位址」,我們使用的指標就是儲存這種 08/29 20:32
GNUGCC:類型的資料,不管它是屬於那一種,甚至是 void*,它儲存的都是 08/29 20:33
GNUGCC:記憶體位址,各位應該常看到 16 進位的指標變數對吧?或者是 08/29 20:34
GNUGCC:前幾位網友利用「強制轉型」的方式讓編譯器用不同的型態對 08/29 20:37
GNUGCC:這個位址做不同的解讀,或甚至把它轉換成正整數型態也會發現 08/29 20:39
GNUGCC:像是 void* 轉成 int 型態,可以發現這 2 個變數內容一樣,例 08/29 20:41
GNUGCC:如 : 08/29 20:41
GNUGCC:void *pv; // 這個系統會隨意給一個值 08/29 20:41
GNUGCC:上面敘述改成這樣 : 08/29 20:45
GNUGCC:void *pv = malloc(100); 08/29 20:46
GNUGCC:int Address = (int)pv; // 把指標型態轉成整數 08/29 20:47
GNUGCC:cout << pv << endl << Addres; 08/29 20:47
GNUGCC:會發現這 2 個變數儲存的內容一模一樣,只是進位表示的方式 08/29 20:48
GNUGCC:不同,這個就是我之前在跟大家討論的觀念. 08/29 20:49
suhorng:可是那 member func ptr 大小不一樣又是? 08/29 20:49
GNUGCC:s 大大,您說的是資料型態本身的大小,每一種編譯器給予不同 08/29 20:54
GNUGCC:的型態會有不同的實作方式,但「資料型態大小」不管是多少它 08/29 20:56
GNUGCC:還是只儲存記憶體位址而已,並不影響程式執行結果. 08/29 20:56
azureblaze:可是member func ptr明明就不只儲存記憶體位置 08/29 21:06
GNUGCC:azureblaze : 怎麼說呢? 08/29 21:12
GNUGCC:不然您覺得它應該還有儲存什麼呢? 08/29 21:16
azureblaze:記憶體位置只要8個byte的時候sizeof(mfp)=16存垃圾嗎? 08/29 21:17
Fenikso:執行檔很大 需要128bit定址(大誤) 08/29 21:18
azureblaze:http://ppt.cc/xue- 1/3的地方有各編譯器的layout. 08/29 21:18
GNUGCC:這樣講好了,當您輸出這個「指向成員函式的指標」,請問您看 08/29 21:22
GNUGCC:到了什麼? 08/29 21:22
azureblaze:指標不是記憶體位置 是更高階的語言概念 08/29 21:22
GNUGCC:先不管它的資料型態多大,您只要說出螢幕上看到的. 08/29 21:23
azureblaze:輸出是錯的 printf和iostream不知道怎麼解讀成員指標 08/29 21:24
GNUGCC:azureblaze : 那您可能沒看到前幾位網友的方法,請往前看記 08/29 21:25
GNUGCC:錄唷,那裡都有詳細的說明. 08/29 21:25
Feis:printf("%d\n", 3.5); 哇! 3.5 果然是整數! 錯怪你了 08/29 21:26
GNUGCC:F 大大,這裡純屬討論區,不是嘴炮討論區,請維持該區的品質, 08/29 21:29
GNUGCC:謝謝! 08/29 21:29
Feis:"您只要說出螢幕上看到的".. 我看到了整數! 08/29 21:30
Feis:不然您看到什麼?? 08/29 21:30
azureblaze:他只輸出了前面4個byte而已,剩下是什麼? 08/29 21:30
GNUGCC:您還沒告訴我您看到了什麼 08/29 21:31
azureblaze:您還沒告訴我為什麼大小不一樣 08/29 21:31
GNUGCC:我先問的問題,應該是您先要回答我吧 08/29 21:36
azureblaze:我回答了顯示是錯的 你要不要回我sizeof是錯的? 08/29 21:38
GNUGCC:前面網友提供的方法您用過了嗎? 08/29 21:53
azureblaze:到底是哪一個 08/29 21:53
GNUGCC:azureblaze : 這位大大,如果您有問題,請注意您的發問態度, 08/29 22:01
GNUGCC:用這種口氣在質問不如自已找答案吧. 08/29 22:03
azureblaze:http://ideone.com/1U5Mrg 08/29 23:08
azureblaze:如果只有記憶體位址為什麼pC有8個byte? 08/29 23:08
azureblaze:第五個byte的8是做什麼的? 08/29 23:09
azureblaze:如果printf是正確的為什麼把值塞回去後8沒有一起? 08/29 23:10
azureblaze:為什麼8不見之後指標呼叫的結果就變了? 08/29 23:10
worldlet:G大扯到最後,還是F大明智,有先見之明。 08/29 23:20
worldlet:早已明瞭G大在想些甚麼。 08/29 23:20
worldlet:F大在 17993 的推文(8/26 23:54)已經就這麼說了 08/29 23:20
worldlet:"你要這麼說全部格式都是整數阿. 廢話." 08/29 23:20
worldlet:"不巧影片、照片. 哇! 連我的 Word 檔都是整數型態." 08/29 23:20
worldlet:"真是太神奇了, 傑克!" 08/29 23:21
worldlet:對照G大以上的發言,簡直完全符合!! 08/29 23:21
worldlet:幫大家重點整理一下G大的心路歷程懶人包 08/29 23:21
worldlet:先是說: 08/29 23:21
worldlet:"指標的強制轉型寫法不管那一種編譯器仍會完成轉型動作" 08/29 23:21
worldlet:被打槍! 08/29 23:21
worldlet:然後只好硬凹成: 08/29 23:22
worldlet:"全部格式都是整數,所以記憶體位址也不例外" 08/29 23:23
worldlet:言下之意就是: 08/29 23:23
worldlet:"要轉當然可以轉阿,轉不成功只是編譯器不實作嘛 !!" 08/29 23:23
worldlet:以上,整理完畢,節省大家看落落長推文的時間,謝謝。 08/29 23:23
azureblaze:幫G大找台階下好了,他在講C不是C++。 08/29 23:32
GNUGCC:我現在才知道原來有些人喜歡移花接木. 08/30 00:12
GNUGCC:W 大大,您如果不懂某些方面的理論可以看其他主題的文章. 08/30 00:13
GNUGCC:這裡是屬於程式設計討論區,不是嘴炮專用討論區. 08/30 00:14
GNUGCC:可以建議版主喜歡刻意去謀黑言論的人勿讓他再進來,以免破壞 08/30 00:16
GNUGCC:討論區的品質. 08/30 00:16
BlazarArc:......太幽默了 08/30 00:33
xatier:GNUGCC 大大我想請教您對於我貼出來的 C spec 怎麼看 09/01 06:55
xatier:說話啊!還是英文太難您看不懂? 09/02 11:29
LPH66:這種時候應該要丟個他想看的東西上來才行 09/03 18:36
LPH66:他不想看的東西他是怎樣都不會回應的 (像你我二人的文章) 09/03 18:37
LPH66:於是這裡是個他應該有興趣的東西: http://ideone.com/jBEPDT 09/03 18:37
LPH66:基本上這段程式所印出的就是他所想要的"指標的實際內容數" 09/03 18:38
LPH66:問題來了: 試解釋兩個印出 &Child::three 與 &Child::four 09/03 18:39
LPH66:的四個"數"究竟代表著什麼位址 09/03 18:40
LPH66:啊, 我的問題是對著 G 大發問的唷 ^^ 09/03 18:40
GNUGCC:這些問題可以去看 descent 大大發表的討論文章,裡面都有說 09/04 19:45
GNUGCC:明,不懂理論的請以「不恥下問」的態度來發問,謝謝. 09/04 19:46
Feis:所以 G 大不知道 descent 的 code 有問題. 哈哈 09/05 01:14
LPH66:我可以將樓樓上的發言視為你已經放棄堅持那結果是一個數嗎? 09/05 09:18
LPH66:那麼這便是跟你自己之前的發言自相矛盾了 09/05 09:19
GNUGCC:descent 大大的 code 我在 Visual C++ 2008 是沒問題的唷^^ 09/05 23:08
GNUGCC:不過不確定其他編譯器是否有問題,不過看過了 LPH66 大大給 09/05 23:09
GNUGCC:的範例程式後發現在 Visual C++ 2008 應該是不可行,至於為 09/05 23:10
GNUGCC:什麼我想大家都知道了,如果還是不懂為何請自行發問,至於大 09/05 23:13
GNUGCC:家一直對於輸出結果倒底是什麼「數」可以去看 descent 大大 09/05 23:17
GNUGCC:使用 Visual C++ 2010 與 GCC 編譯器輸出的結果應該能推測 09/05 23:18
GNUGCC:為何輸出的結果它的「特性」會相差很大了. 09/05 23:19
GNUGCC:本人再次強調,我討論的重點是在於記憶體位址的「特性」,跟 09/05 23:22
GNUGCC:編譯器實作的技術並無直接關連,因為不管實作技術為何,CPU 09/05 23:23
GNUGCC:永遠都只使用「記憶體位址」在存取資料,各位只是看到表面上 09/05 23:26
GNUGCC:被包裝後的結果,如此而已. 09/05 23:29
LPH66:好吧, 看來只有你一個人站的高度不一樣而已 (攤手) 09/05 23:33
LPH66:這一串從頭到尾都在談 C/C++ 語言裡的指標 09/05 23:33
LPH66:然而我現在才終於發現原來你站的比我們討論的高度還高 09/05 23:33
LPH66:抽象層已經高到雲深不知處了 難怪你跟我們之間一直沒交集.. 09/05 23:34
LPH66:嘛, 還是要說一句小心高處不勝寒啊... 09/05 23:35