→ 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