呣,其實我大一的時候也有這種觀念,畢竟那時 pointer 還是個陌生的怪物,那還是個「如果你不會傳 array 就宣告成 global」的時代。
基本上 C 的 array 實在不怎麼討喜,包括它的「陣列大小一定要跟在陣列名稱後面」這種鳥語法,如果再加上 function pointer 那可真是醜斃了。之所以 array 經常和 pointer 混為一談,最大的原因應是 array 會被隱式轉型[?]為 pointer,且 array 變數本身的值就是 array 第一個元素的位址。這讓你可以把陣列丟入如下的函式裡:
基本上 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 ); }以此類推。
std::size_t N, std::size_t M 會自行推導,從 C++ Compiler Message 是推的出來的,如果我沒猜錯的話 XD。
回覆刪除tmplate XD
ouch ... stupid typo = =
回覆刪除可是我如果不用 reference 它就無法推導說
VC 9.0 和 gcc 4.3 的結果
猜測是用 pointer type 時,就會自動轉型了,為了向下相容 C 的結果,array type 本身應該是有帶有 array size 的,這是我看 C++ compiler message 的猜測 XD。
回覆刪除陣列和指標是什麼我不會
回覆刪除但重點是你明明在高中就在玩指標了 = =+
老實說,我覺得我到現在還是不太會用指標做出精巧的程式,每次用 inheritance 總是會想到 function pointer table ...
回覆刪除@yen3:
回覆刪除我想你說得沒錯
可能 C++ 沒有設定 array varible 的 copy 行為
至於是不是向 C 相容,我持保留態度
因為現行的 C99 和 C++ 己不完全相容了
說起來我也忘了提"不要在陣列內存放多型指標"
不過那是 C++ 才有的問題
@johnroyer:
我高中時期還是不擅長指標啊 orz
拜 m(_ _)m
回覆刪除