TAG

首都機能移轉 (2) 歌詞 (2) 靠北文 (40) 戲言 (30) 糟糕 (7) ACG (23) Assembly (2) Boost (2) C (31) C++ (69) CMake (4) CSIE (67) Debian (34) Design_Pattern (2) Django (1) Eclipse (1) en_US (13) FFmpeg (3) FoolproofProject (26) FreeBSD (2) Git (4) GNU_Linux (65) IDE (5) Java (11) JavaScript (19) KDE (15) Khopper (16) KomiX (3) Kubuntu (18) Life (1) Lighttpd (2) Mac_OS_X (2) Opera (1) PHP (2) PicKing (2) Programing (21) Prolog (1) Python (7) QSnapshot (2) Qt (30) Qt_Jambi (1) Regular_Expression (1) Shell_Script (7) Talk (98) VirtualBox (7) Visual_Studio (13) Windows (18) zh_TW (36)

2009年11月29日 星期日

Array IS NOT pointer

呣,其實我大一的時候也有這種觀念,畢竟那時 pointer 還是個陌生的怪物,那還是個「如果你不會傳 array 就宣告成 global」的時代。
基本上 C 的 array 實在不怎麼討喜,包括它的「陣列大小一定要跟在陣列名稱後面」這種鳥語法,如果再加上 function pointer 那可真是醜斃了。之所以 array 經常和 pointer 混為一談,最大的原因應是 array 會被隱式轉型[?]為 pointer,且 array 變數本身的值就是 array 第一個元素的位址。這讓你可以把陣列丟入如下的函式裡:
void f1( const int * array );
呃,那二維陣列呢?
void f2( const int * * const array );
因為並不存在多維陣列對 pointer 的隱式轉換,因此你無法直接丟進去。
接下來要談談 array 和 pointer 有什麼不同。
最顯著的性質是,array 變數本身是唯讀的,它無法再被賦值,其代表的空間也無法被手動釋放,而 pointer 值則可以變動,指向的內容可能可以被手動釋放;這也是 pointer 令新手感到易混淆的地方,因為它同時有資源的持有者以及迭代性質。
此外,pointer 可以被取址,但是 array 的址和它自己一樣,也就是陣列開始的第一個位址:
int cla[1];
printf( "%p %p\n", cla, &cla );    // the same
另一個較為有用的不同點是,array 可利用 sizeof 求大小,而 pointer 就只是個 pointer。
int8_t a[10];
sizeof( a ); // 10
int8_t * b = a;
sizeof( b ); // 4 or 8, depends on your compiler
那如果你很希望陣列在傳入函式後還是個陣列,C++ 的 template 可以幫得上忙:
template< typename T, std::size_t N >
std::size_t getByteLength( const T ( & array )[N] ) {
    return sizeof( array );
}

// how to use:
int32_t tmp[4];
getByteLength( tmp );  // will return 16
坦白說,我不是很清楚為什麼一定要用 reference to array,不過你的確可以用這個 template function 傳 array。再多維也可以:
template< typename T, std::size_t N, std::size_t M >
std::size_t getByteLength2( const T ( & array )[N][M] ) {
    return sizeof( array );
}
以此類推。

7 則留言:

  1. std::size_t N, std::size_t M 會自行推導,從 C++ Compiler Message 是推的出來的,如果我沒猜錯的話 XD。

    tmplate XD

    回覆刪除
  2. ouch ... stupid typo = =

    可是我如果不用 reference 它就無法推導說
    VC 9.0 和 gcc 4.3 的結果

    回覆刪除
  3. 猜測是用 pointer type 時,就會自動轉型了,為了向下相容 C 的結果,array type 本身應該是有帶有 array size 的,這是我看 C++ compiler message 的猜測 XD。

    回覆刪除
  4. 陣列和指標是什麼我不會
    但重點是你明明在高中就在玩指標了 = =+

    回覆刪除
  5. 老實說,我覺得我到現在還是不太會用指標做出精巧的程式,每次用 inheritance 總是會想到 function pointer table ...

    回覆刪除
  6. @yen3:
    我想你說得沒錯
    可能 C++ 沒有設定 array varible 的 copy 行為
    至於是不是向 C 相容,我持保留態度
    因為現行的 C99 和 C++ 己不完全相容了

    說起來我也忘了提"不要在陣列內存放多型指標"
    不過那是 C++ 才有的問題

    @johnroyer:
    我高中時期還是不擅長指標啊 orz

    回覆刪除