看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《wope (獨立黑色色彩)》之銘言: : 開發平台(Platform): (Ex: VC++, GCC, Linux, ...) : GCC4.7.2 MinGW64 : 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) : NO : 問題(Question): : 想請問"寫法1"與"寫法2"的差別是什麼 : 寫法1: MF2KGMG_operator* GMG_ptr=(MF2KGMG_operator*) GMGID; : 寫法2: MF2KGMG_operator* GMG_ptr=(MF2KGMG_operator*)*GMGID; : 這是Modflow 的原始碼 : 下載時他的程式為"寫法2" : 但會出現waning: : cast from pointer to integer of different size [-Wpointer-to-int-cast] : 但 : 我改成"寫法1"時waning不見了 : 可是我不懂語法上的義意 : 問題如下 : (1)想請版上的高手這樣改裡面的值會不會一樣? : (2)語法上的義意差在哪裡? : __ : 其中 : GMGID與MF2KGMG_operator定義如下 : int* GMGID : typedef struct MF2KGMG_operator : { : r_data rd; /* Vector Data */ : r_vector r; /* Residual */ : r_vector z; /* Head-Change */ : GEN_operator CCFD; /* Cell-Centered Finite Difference Matrix */ : GEN_operator CCFDMG; /* Multilevel CCFD Operator */ : GEN_operator PCG; /* Preconditioned Conjugate Gradient */ : double w; /* Relaxation Parameter */ : CCFD_operator *CCFD_ptr; /* Pointer to access CCFD operator */ : }MF2KGMG_operator; : MF2KGMG_operator* GMG_ptr=(MF2KGMG_operator*)*GMGID; : MF2KGMG_operator* GMG_ptr=(MF2KGMG_operator*) GMGID; 我去找到了似乎是你的程式的來源 這裡的使用情境看起來 GMGID 所指向的 int 是個類似 HANDLE 之類的存在 那個 int 其實是一個 MF2KGMG_operator * 可以參看 MF2KGMG_ALLOCATE 的最後 就在你問的程式的上面幾行 (#153) *GMGID = (int)GMG_ptr; 所在做的就是這麼回事 MF2KGMG_ALLOCATE 的 GMGID 是個 "call by address" #153 就是在把做出來的東西給"回傳"回去 你問的 MF2KGMG_FREE 的這個 GMGID 其實也是一樣 所以函式裡必須要先 dereference 才能得到實際的 HANDLE 因此寫法 2 才是正確的 寫法 1 會把那個指向 HANDLE 的指標解釋成 MF2KGMG_operator 的指標 這是錯誤的 如果要消掉這個 warning 的話 照理說中間多轉一層 (intptr_t) 就可以了 不過這支程式這麼做的地方還不少 所以...我覺得放著也沒差就是了 -- LPH [acronym] = Let Program Heal us -- New Uncyclopedian Dictionary, Minmei Publishing Co. -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 210.69.49.38
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:該是推這東西出來的時候了 http://tinyurl.com/3d487sk 08/25 01:34
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