精華區beta C_and_CPP 關於我們 聯絡資訊
unsigned int * p; unsigned int x,y; 用sizeof看 p : 8 bytes x : 4 bytes y : 4 bytes 能夠把p拆成兩半存進x,y 之後在把x,y組合成p嗎? =============================================== typedef struct{ unsigned int x; unsigned int y; }UI; typedef union{ unsigned int* p; UI i; }MYTYPE; 這樣還蠻方便的@@ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.129.35.39
LPH66:union 你是 64-bit 的系統對吧? 08/31 00:44
deepking:是的~還沒用過union說,來試看看~thx 08/31 00:46
※ 編輯: deepking 來自: 220.129.34.102 (08/31 11:18) > -------------------------------------------------------------------------- < 作者: samuelcdf (溫泉龜) 看板: C_and_CPP 標題: Re: [問題] 能將指標拆成整數儲存嗎? 時間: Tue Aug 31 01:46:42 2010 ※ 引述《deepking (wnuiayldh)》之銘言: : unsigned int * p; : unsigned int x,y; : 用sizeof看 p : 8 bytes : x : 4 bytes : y : 4 bytes : 能夠把p拆成兩半存進x,y : 之後在把x,y組合成p嗎? 先說一下, 這是用指標的寫法, 至於p[0], p[1]哪一個該assign 到x中, 得看endian決定 雖然按照學到的知識, 了解這樣做是可以的. 可是在這種情況下, 用感覺來說, 會有種說不上來奇怪的感覺, 不知道有沒有人跟我 一樣 XDD int main(int argc, char *argv[]) { int TestNumber; int* pInteger = &TestNumber; unsigned int* p = (unsigned int*)&pInteger; printf("Sizeof int*: %d\n", sizeof(int*)); printf("Sizeof int: %d\n", sizeof(int)); printf("\n%p\n", pInteger); printf("\n[%08X]\n", p[0]); printf("\n[%08X]\n", p[1]); system("PAUSE"); return 0; } 32位元可以用short模擬一下 XD int main(int argc, char *argv[]) { short TestNumber; short* pShort = &TestNumber; unsigned short* p = (unsigned short*)&pShort; printf("Sizeof short*: %d\n", sizeof(short*)); //4 printf("Sizeof short: %d\n", sizeof(short)); //2 printf("\n%p\n", pShort); printf("\n[%04X]\n", p[0]); printf("\n[%04X]\n", p[1]); system("PAUSE"); return 0; } -- -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.32.51.239 > -------------------------------------------------------------------------- < 作者: tinlans ( ) 看板: C_and_CPP 標題: Re: [問題] 能將指標拆成整數儲存嗎? 時間: Tue Aug 31 05:49:51 2010 ※ 引述《samuelcdf (溫泉龜)》之銘言: : 先說一下, 這是用指標的寫法, 至於p[0], p[1]哪一個該assign : 到x中, 得看endian決定 : 雖然按照學到的知識, 了解這樣做是可以的. 可是在這種情況下, : 用感覺來說, 會有種說不上來奇怪的感覺, 不知道有沒有人跟我 : 一樣 XDD : int main(int argc, char *argv[]) : { : int TestNumber; : int* pInteger = &TestNumber; : unsigned int* p = (unsigned int*)&pInteger; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^自殺行為 : printf("Sizeof int*: %d\n", sizeof(int*)); : printf("Sizeof int: %d\n", sizeof(int)); ^^^^ 這邊應該用 %zu 節錄自 FreeBSD 的 man page: Modifier d, i o, u, x, X n hh signed char unsigned char signed char * h short unsigned short short * l (ell) long unsigned long long * ll (ell ell) long long unsigned long long long long * j intmax_t uintmax_t intmax_t * t ptrdiff_t (see note) ptrdiff_t * z (see note) size_t (see note) q (deprecated) quad_t u_quad_t quad_t * : printf("\n%p\n", pInteger); : printf("\n[%08X]\n", p[0]); : printf("\n[%08X]\n", p[1]); : system("PAUSE"); : return 0; : } > gcc -v Using built-in specs. Target: x86_64-portbld-freebsd8.1 Thread model: posix gcc version 4.4.5 20100720 (prerelease) (GCC) > gcc -O3 -Wall test.c -o test test.c:11: warning: dereferencing pointer 'p' does break strict-aliasing rules test.c:5: note: initialized from here test.c:12: warning: dereferencing pointer '({anonymous})' does break strict-aliasing rules test.c:12: note: initialized from here > ./test Sizeof int*: 8 Sizeof int: 4 0x7fffffffe86c [FFFFE8A0] [00007FFF] 如果想要拿 pointer 拆這種東西, 最保險的方法是轉成 char * 去慢慢爬。 因為往 char * 的 casting 有特殊規則在, aliasing 的關係不會因為 pointer type 不同而自動消滅。 union 的解法雖然標準沒有保證, 不過大部分的 compiler 都支援那種技巧。 所以你大部分看到的可能還是拿 union 去拆。 -- Ling-hua Tseng (uranus@tinlans.org) Department of Computer Science, National Tsing-Hua University Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design Researching: Software pipelining for VLIW architectures Homepage: http://www.tinlans.org -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.160.110.176 ※ 編輯: tinlans 來自: 118.160.110.176 (08/31 14:16) > -------------------------------------------------------------------------- < 作者: samuelcdf (溫泉龜) 看板: C_and_CPP 標題: Re: [問題] 能將指標拆成整數儲存嗎? 時間: Wed Sep 1 00:24:29 2010 ※ 引述《tinlans ( )》之銘言: (恕刪) : > gcc -v : Using built-in specs. : Target: x86_64-portbld-freebsd8.1 : Thread model: posix : gcc version 4.4.5 20100720 (prerelease) (GCC) : > gcc -O3 -Wall test.c -o test : test.c:11: warning: dereferencing pointer 'p' does break strict-aliasing rules : test.c:5: note: initialized from here : test.c:12: warning: dereferencing pointer '({anonymous})' does break : strict-aliasing rules : test.c:12: note: initialized from here : > ./test : Sizeof int*: 8 : Sizeof int: 4 : 0x7fffffffe86c : [FFFFE8A0] : [00007FFF] : 如果想要拿 pointer 拆這種東西, : 最保險的方法是轉成 char * 去慢慢爬。 : 因為往 char * 的 casting 有特殊規則在, : aliasing 的關係不會因為 pointer type 不同而自動消滅。 : union 的解法雖然標準沒有保證, : 不過大部分的 compiler 都支援那種技巧。 : 所以你大部分看到的可能還是拿 union 去拆。 感謝原PO讓我增長見識. 補充一下, 原PO所說的 strict-aliasing rule 算是一種假設, 當此種假 設打開的時候, compiler能夠根據這個假設, 作進一步的最佳化. (在-O3時) 所以當自己寫的程式並不符合這個假設時, compiler作最佳化所產生的code, 可能會產生意料外的結果. 解決的方法就如原PO所寫的, 或是把這個假設關 閉. *strict-aliasing rule: 不同型態的指標, 不會指到同一個記憶體位置上 這邊有詳細說明: http://tinyurl.com/opgb56 心得: 想要讓compiler產生最佳化的code, 自己最好弄清楚compiler對程式碼 作了哪些假設. 不然最佳化最好不要開到最高等級 XD -- -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.32.51.239
loveme00835:記更通用的解法比較簡單 ~"~ 09/01 00:39
samuelcdf:是的. 只是把詳細原因分享一下而已 09/01 00:59
> -------------------------------------------------------------------------- < 作者: tinlans ( ) 看板: C_and_CPP 標題: Re: [問題] 能將指標拆成整數儲存嗎? 時間: Wed Sep 1 02:10:57 2010 ※ 引述《samuelcdf (溫泉龜)》之銘言: : 感謝原PO讓我增長見識. : 補充一下, 原PO所說的 strict-aliasing rule 算是一種假設, 當此種假 : 設打開的時候, compiler能夠根據這個假設, 作進一步的最佳化. (在-O3時) : 所以當自己寫的程式並不符合這個假設時, compiler作最佳化所產生的code, : 可能會產生意料外的結果. 解決的方法就如原PO所寫的, 或是把這個假設關 : 閉. : *strict-aliasing rule: 不同型態的指標, 不會指到同一個記憶體位置上 : 這邊有詳細說明: : http://tinyurl.com/opgb56 : 心得: : 想要讓compiler產生最佳化的code, 自己最好弄清楚compiler對程式碼 : 作了哪些假設. 不然最佳化最好不要開到最高等級 XD 事實上這個最佳化在 -O2 就已經開了。 只是你的 code 太簡單只有一個 main function 又只有一個編譯單元, 所以要觸發問題需要開到 -O3。 一般來說規模大一點的光開 -O2 就夠了。 這也是為什麼你編譯一些 open source 的程式時, 常看到 -fno-strict-aliasing 這參數會串在 -O2 後面。 至於你的心得... 原本我想說一個某對男女交往之後男生一直踩到女生地雷, 雖然男生每次踩到女生地雷都不會再犯第二次, 然而他總是可以踩到連女生自己都不見得知道的地雷, 最後搞到女生受不了終於在去年七夕跟他分手的故事。 但是這樣公開八卦別人的事情好像有失厚道, 而且要打很多字會打到天亮還不見得有人看得懂我想說什麼, 所以我想還是算了。 這個心得的問題在於你把焦點放到 compiler 這一層級上, 而不是放在更根本的語言標準層級上。 如果語言標準沒有允許 compiler 做這種假設, compiler 也不會擅自做這麼大膽的假設去搞爛你的 code。 與其去個別瞭解 compiler 做了哪些假設, 倒不如去瞭解語言本身對你寫的 code 提供了多少保證。 否則很多事情永遠只能治標, 並不能治本。 雖然 strict aliasing 這名詞沒有出現在語言標準裡, 但 C99 規格書的 6.5 paragraph 7 (p.68) 說: An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 73) - a type compatible with the effective type of the object, - a qualified version of a type compatible with the effective type of the object, - a type that is the signed or unsigned type corresponding to the effective type of the object, - a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, - an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or - a character type. ------------------------- 73) The intent of this list is to specify those circumstances in which an object may or may not be aliased. 如果你做了語言標準不是 100% 保證會怎樣的事, 那麼 compiler 會怎樣編譯你的 code 都不意外。 也許你現在手邊的 compiler 現在的確做了某些假設而你也完全瞭解, 但是下週或下個月裝了一個 update 後它的假設又變了。 如果你總是在忙著去重新瞭解你的 compiler 會做哪些假設, 我個人會覺得這是一個充滿著忙碌的人生。 當然這一切的一切都是看主角的個人喜好, 畢竟我也是認識不少人就是喜歡這麼忙碌地生活著。 所以我只會在一開始給一些建議, 並不會去強求什麼。 -- Ling-hua Tseng (uranus@tinlans.org) Department of Computer Science, National Tsing-Hua University Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design Researching: Software pipelining for VLIW architectures Homepage: http://www.tinlans.org -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.160.110.176
softwind:推~ 09/01 02:13