推 wope:感謝~~ 了解了 08/23 17:26
→ GNUGCC:其實不管用那一種寫法,編譯器只要遇到強制轉型動作的話 08/23 21:27
→ GNUGCC:會假設你知道目前正在做什麼事,所以編譯器不會出現錯誤而是 08/23 21:28
→ GNUGCC:顯示警告訊息,這個例子的 GMGID 與 MF2KGMG_operator* 都是 08/23 21:30
→ GNUGCC:32 bit 指標,它可以指向任何型態物件位址,遇到了強制轉型的 08/23 21:33
→ GNUGCC:話,編譯器仍會完成轉型動作,但結果是未知的. 08/23 21:38
→ Feis:強制轉型不一定不會有 Error. 這裡是因為是指標..... 08/24 14:48
推 littleshan:原po用的不是mingw64嗎?那怎麼會是32bit pointer? 08/24 14:57
→ GNUGCC:這裡指的是指標的強制轉型寫法不管那一種編譯器仍會完成轉 08/24 21:25
→ GNUGCC:型動作. 08/24 21:26
→ GNUGCC:要判斷指標是不是 32 bit 可以使用 sizeof(void*) 得到結果 08/24 21:28
推 Feis:樓上大大可示範一下怎麼把指標直接轉 double ? 08/24 22:40
→ Feis:還是可以教教我怎麼在一般情況下讓指標轉成指標有警告訊息? 08/24 22:41
→ Feis:我大概知道 gcc 怎麼開, 但是 Visual C++ 一直找不到~ 08/24 22:49
→ GNUGCC:通常要刻意去寫「從語意上來看不可行,但實作上可行」的敘述 08/24 23:38
→ GNUGCC:屬高階程式設計技巧,要怎麼應用端看目的為何,以這個例子來 08/24 23:39
→ Feis:喔喔. 那可以示範一下嗎? 08/24 23:40
→ GNUGCC:看, GMGID 它是 int 型態,但實際上是 MF2KGMG_operator* 08/24 23:40
→ Feis:示範一下怎麼讓你的 Visual C++ 將 int* 轉成 double 可以嗎? 08/24 23:41
→ GNUGCC:用了強制轉型編譯器就有警告訊息就是一個例子. 08/24 23:41
→ GNUGCC:請問你的目的是? 08/24 23:42
→ Feis:因為你說指標都能轉. 事實上就是不行 08/24 23:42
→ Feis:如果是指標轉指標. 一般情況下也不會有警告. 08/24 23:44
→ GNUGCC:你可以注意看這個例子, *GMGID 轉成 MF2KGMG_operator 物件 08/24 23:45
→ GNUGCC:不就有警告訊息了嗎 08/24 23:45
推 Feis:"指標的強制轉型寫法不管那一種編譯器仍會完成轉型" 08/24 23:45
→ GNUGCC:轉成 MF2KGMG_operator 指標編譯器會給你警告訊息 08/24 23:46
→ Feis:int a; (double)&a; 會過嗎? 08/24 23:47
→ Feis:GMGID 就不是指標. 你在說什麼..... 08/24 23:48
→ Feis:Sorry 我氣到了. 說錯化. 08/24 23:49
→ Feis:我是說 *GMGID 不是指標. 08/24 23:50
→ GNUGCC:GMGID 它是 int * 08/24 23:54
→ GNUGCC:這位大大您誤會我的意思了,我是指「利用指標變數可以指向 08/24 23:55
→ GNUGCC:任何型態的物件」的強制轉型. 08/24 23:55
→ Feis:那哪來你說的警告,算了。不要誤人子弟 08/24 23:58
→ GNUGCC:這個例子難道你看不出來有什麼變化嗎? 08/25 00:01
推 littleshan:哈哈哈哈哈,你以為指標硬轉指標永遠合法嗎? 08/25 00:03
→ GNUGCC:所以才會有警告訊息的用意,這樣您懂了嗎? 08/25 00:04
→ Feis:是是是,int 是指標,我懂了! 08/25 00:09
推 littleshan:我是說,指標轉指標不一定「編得過」,OK? 08/25 00:09
→ Feis:void * 接棒~ 08/25 00:13
→ GNUGCC:如果你看的出來這個例子的變化就知道我在說什麼了. 08/25 00:13
→ GNUGCC:看不出來的話也沒關係,因為這個是屬於「語意不可行」. 08/25 00:14
→ littleshan:「指標變數可以指向任何型態的物件」 Are you sure? 08/25 00:24
→ LPH66:我還蠻建議 GNUGCC 兄可以看一看這個 08/25 01:34
推 GNUGCC:感謝 L 大大提供的資料,不過還是老話一句也就是我說的, 08/25 06:42
→ GNUGCC:「語意上不可行,但實作上可行」的作法編譯器只會給你警告訊 08/25 06:43
→ GNUGCC:息,因為它假設你知道目前正在做什麼事情,強制轉型只是 08/25 06:44
→ GNUGCC:完成你指定的動作,那結果必定是未知的,所以也就不符合 08/25 06:47
→ GNUGCC:「可攜性」. 08/25 06:47
推 SeamusBerloz:驚!看了 L 大提供的資料,才發現自己幹了很多蠢事情 08/25 07:19
→ Feis:GNUCCC: 那有什麼事情是實作上不可行. 只會亂扯. 08/25 10:30
→ Feis:C 指標跟整數型態互轉是implmentation-defined 08/25 10:38
→ Feis:而能這樣直接強制轉型的除了不一定成功的指標也就只有整數 08/25 10:46
→ Feis:難道把位址存在 double, 再將 double 轉指標就是實作不可行? 08/25 11:01
→ Feis:事實上就是語法不可行 08/25 11:01
→ Feis:強制轉型沒有你講的那麼強大. 型態強制轉型還是有規範的 08/25 11:02
→ Feis:而且這警告是pointer-to-int-cast,不是 pointer-to-pointer 08/25 11:10
→ Feis:你搞不清楚這個警告的意涵 08/25 11:11
→ Feis:而且這警告的主要核心還是在於他用的是 64-bit 編譯器 08/25 11:44
→ Feis:sizeof(int) 與 sizeof(int *) 不一樣造成問題 08/25 11:44
→ Feis:抱歉, 應該是 sizeof(*GMGID) 與 sizeof(GMG_ptr) 08/25 11:46
→ Feis:而且 "那結果必定是未知的". 說這種話不會太誇張嗎 08/25 12:06
→ Feis:哇. 好多而且. Q_Q 08/25 12:12
→ EdisonX:看完推文...手癢的衝動... 08/25 13:58
→ a27417332:不好意思想問,為甚麼int*可以轉為int不能轉為double? 08/25 19:54
→ a27417332:純粹只是好奇而已,希望有大大能給文件參考OAO 08/25 19:55
→ a27417332:是因為語法就是規定不行嗎? 08/25 19:56
→ GNUGCC:F 大大,我想您誤會可深了,我說的「實作上可行」是指編譯器 08/25 20:03
→ GNUGCC:會完成轉換動作,但結果是未知的,可想而知結果為不確定性原 08/25 20:05
→ GNUGCC:因就是「雖然已完成轉換動作,但結果可能不是您要的」,即然 08/25 20:08
→ GNUGCC:編譯器會完成轉換對編譯器來就是「實作上可行」,但對結果來 08/25 20:08
→ GNUGCC:說就是「實作上不可行」,不知道這樣有清楚了嗎? 08/25 20:09
推 littleshan:G 大大,我想您誤會可深了。最前面您提到「32bit指標 08/25 21:54
→ littleshan:可以指向任何型態物件位址」這在大部份實作上都是錯的 08/25 21:54
→ littleshan:某些指標強制轉型在幾乎所有compiler上都會error 08/25 21:59
→ littleshan:所以「實作上可行」這句話本身就不成立了 08/25 22:00
→ GNUGCC:指標本身是幾位元型態編譯器會依照作業系統的特性來決定,並 08/25 22:12
→ GNUGCC:不影響執行結果. 08/25 22:13
→ Schottky:指標可以轉型指向任意type,這只有在C成立吧,和32/64無關 08/25 22:13
→ GNUGCC:這個例子就是使用 C 語言的方式在做「強制轉型」. 08/25 22:14
→ Schottky:所以您的意思是C可以宣告物件出來指就對了? 08/25 22:16
→ GNUGCC:如果把這個敘述 (MF2KGMG_operator *) 改成 08/25 22:19
→ GNUGCC:static_cast<MF2KGMG_operator *>(*GMGID); 08/25 22:20
→ GNUGCC:編譯器就會出現錯誤了,但相對的改成 08/25 22:21
→ GNUGCC:reinterpret_cast<MF2KGMG_operator *>(*GMGID); 08/25 22:21
→ GNUGCC:這個結果跟用 C 語言的方式相同. 08/25 22:21
→ GNUGCC:C 語言本身的 struct 跟 C++ 的 class 是大同小異的. 08/25 22:23
推 descent: int a=5; double d = *((double *)&a); 08/26 17:54
→ descent:這樣可以轉成 double, 不過我怕我誤會推文的意思 08/26 17:55
→ descent:因為我不是很懂推文討論的東西 08/26 17:56
推 purpose:double d = (double)&a; 才是上面想要的 "直接轉 double" 08/26 18:21
→ a27417332:那個推文是硬幹double,不過我還蠻好奇,編譯器可以允許 08/26 18:56
→ a27417332:硬轉int,為何不行硬轉double?是設計上有何考量? 08/26 18:57
→ a27417332:至於我也看不太懂討論,總覺得語法上不可行,實作上可行 08/26 18:57
→ a27417332:這東西好像在幾位大大的認知出有出入?雖然我看不懂QQ 08/26 18:58
推 purpose:有 CPU 指令,執行後可把 int 轉成 double,用硬體去轉換 08/26 19:24
→ purpose:你把指標轉形成 int,雖然位元組不一定相等,但至少你同意 08/26 19:25
→ purpose:可是寫 double d = (double) ptr; 就等先 int 再轉 double 08/26 19:26
→ purpose:從程式碼字面上,完全看不出來,你有同意電腦先轉成 int 08/26 19:27
→ GNUGCC:看來各位好像不太能理解其中的道理,各位要記得,記憶體位址 08/26 20:02
→ GNUGCC:永遠都是「無號數整數型態」,float 與 double 是屬於實數型 08/26 20:03
→ GNUGCC:態,所以編譯器就不允許把記憶體位址轉成實數型態,其實真的 08/26 20:07
→ GNUGCC:不能轉嗎?當然不是,只是最後還是要透過 FPU 做實數轉整數的 08/26 20:08
→ GNUGCC:過程,這樣等於畫蛇添足,與其這樣不如以整數來取位址是明智 08/26 20:10
→ GNUGCC:選擇. 08/26 20:10
→ Feis:記憶體位址永遠是無號正整數?G大不要一直以管窺天 08/26 20:40
→ azureblaze:標準只要求指標能轉整數而已,連怎麼轉都沒規定 08/26 20:44
→ GNUGCC:F 大大,並非以管窺天,只是在講解其中理論. 08/26 20:58
推 Feis:標準實際上也沒保證 08/26 21:02
→ GNUGCC:所以我才會說「語法上不可行,但實作上可行」. 08/26 21:10
推 Feis:3語法上不可行你是怎麼編譯過? 08/26 21:11
→ a27417332:還蠻好奇有那些機器的記憶體位址是違反無號正整數? 08/26 21:12
→ a27417332:總覺得目前的眼界還是太小XDlll感覺有好多不可思議的事 08/26 21:13
→ GNUGCC:就我一直在說的「強制轉型」,這樣想好了,之所以會強制轉型 08/26 21:15
→ GNUGCC:是因為敘述不符合邏輯,如果不使用強制轉型,編譯器馬上會提 08/26 21:16
→ GNUGCC:出「型態不符合」,強制轉型只是讓編譯器知道你很清楚目前正 08/26 21:17
→ GNUGCC:在做什麼事情,所以編譯器仍會完成轉換,但結果是不是您要的 08/26 21:18
→ GNUGCC:就不得而知了. 08/26 21:19
→ GNUGCC:記憶體位址對任何機器來說都是屬於連續的位址編號,並不會有 08/26 21:24
→ GNUGCC:所謂的違反問題,就好像住家地址不可能以自已的姓名代表一樣 08/26 21:25
→ Feis:a27417332: 那你可能要先定義什麼是無號正整數 08/26 22:12
→ a27417332:就順著話講下來的0.0所以我也不太清楚是什麼意思 08/26 22:27
→ Feis:a27417332: 那你接受可能沒有整數型態存得入記憶體位址嗎? 08/26 22:38
→ a27417332:如果有實例的話,應該是能理解@@ 08/26 22:45
→ caras:補充一下,Feis是指有些address大到存不進正常的整數type 08/26 22:46
→ Feis:GNUCCC: 不是所有記憶體模型都是 flat 的 08/26 23:13
→ Feis:標準不把話說死就是要保留高階語言的彈性. 這是C語言特性 08/26 23:15
→ GNUGCC:記憶體模型只是關係到程式的活動範圍,flat 只能在 Windows 08/26 23:34
→ GNUGCC:的保護模式下運行,它只有一個區段,裡面保存程式區段與資料 08/26 23:39
→ GNUGCC:區段也包含使用的資源,它能存取的範圍可以是整部電腦實體記 08/26 23:40
→ GNUGCC:憶體或者是透過作業系統的虛擬記憶體來決定存取的範圍,但不 08/26 23:41
→ GNUGCC:論是使用那一種記憶體模型,CPU 都是使用所謂的「區段值」與 08/26 23:43
→ GNUGCC:「位移值」的方式來存取記憶體,CPU 本身的暫存器都只能儲存 08/26 23:46
→ GNUGCC:整數而已,只有一個例外就是 CPU 本身內含的 FPU 暫存器才能 08/26 23:48
→ GNUGCC:儲存 IEEE 浮點數,CPU 在做間接取值的時候也都是使用一般用 08/26 23:50
→ GNUGCC:途的暫存器,內含的都只有整數而已,各位可以試看看這個 : 08/26 23:53
→ Feis:講 C 語言可以扯到暫存器. G大也是奇葩 08/26 23:53
→ Feis:你要這麼說全部格式都是整數阿. 廢話. 08/26 23:54
→ GNUGCC:在命令提示字元下輸入 : debug 然後按 Enter 08/26 23:54
→ Feis:不巧影片、照片. 哇! 連我的 Word 檔都是整數型態. 08/26 23:55
→ GNUGCC:然後按 r, 可以看到 CPU 全部的暫存器 16 進元的數值 08/26 23:55
→ Feis:真是太神奇了, 傑克! 08/26 23:55
→ GNUGCC:學過電腦的人都應該知道電腦本身只有 0 與 1 的數字,對吧? 08/26 23:56
→ purincess:可惜你正在使用的cpu是使用 page number 跟 page offset 08/26 23:56
→ purincess:(飄走 08/26 23:56
→ GNUGCC:我剛試過, Windows 7 好像不支援 debug 指令... 08/26 23:57
→ GNUGCC:F 大大,您講到重點了,全部格式都是整數,所以記憶體位址也不 08/27 00:01
→ GNUGCC:例外不是嗎? 08/27 00:01
→ Feis:是是是! 您說得對! 反正不是 C 語言嘛 08/27 00:03
→ GNUGCC:我剛說的這些理論只是要說明為何記憶體位址是整數而不是其 08/27 00:06
→ GNUGCC:他非整數的表示方式,跟語言無關,必竟不管使用那一種語言最 08/27 00:08
→ GNUGCC:後都會轉為機器碼,如此而已. 08/27 00:09
→ Feis:是阿 是阿 我們學機器語言就好了嘛. 哎呀呀. C 落伍了 08/27 00:11
→ purincess:樓上XDDDD 08/27 00:12
→ GNUGCC:Page number 與 Page Offset 是屬於虛擬記憶體的部份,可能 08/27 00:13
→ purincess:讓我想到以前直接算好IEEE754 的我要的float的表示法in 08/27 00:13
→ purincess:hex 然後直接用mov塞進記憶體 XD 08/27 00:13
→ GNUGCC:要另外討論了. 08/27 00:13
→ Feis:我要改行不要教 C 語言了. (失業中) 08/27 00:15
→ GNUGCC:Feis : 怎麼說呢? 08/27 00:18
→ purincess:我們都改學brainfuck八 反正都turing complete 08/27 00:18
→ Feis:我怕我寫一寫會罵髒話 08/27 00:21
→ GNUGCC:噗... 08/27 00:21
→ xatier:寫 brainfuck 很好玩啊! 08/27 23:06