為什麼這篇c指標鄉民發文收入到精華區:因為在c指標這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者khoguan (Khoguan Phuann)看板C_and_CPP標題Re: [討論] 關於...
c指標 在 Amber Physiotherapist, MSc Instagram 的最佳解答
2021-09-16 07:45:34
哈囉各位大家好,我是魍魅物理治療師Amber~ 📱使用手機真的會讓你姿勢變差嗎? 🤘🏻先評估你的脖子是否有姿勢變差以及前傾問題? 臨床上會測量顱頸角度(craniovertebral angle, CVA)來當作頭部前傾的指標。小於50-53度則代表有頭部前傾的問題,角度越小,代表脖子障...
※ 引述《gocpp (cpp)》之銘言:
: 一般有幾種習慣:
: T* p; // 向型別 T 看齊
: T *p; // 向變量 p 看齊
: T * p; // 不偏不倚
這的確是見仁見智,style 一致就好。
像是 int* p; 和 int *p;
第一種是強調 type,也就是說 p 的 type 是 int*,
第二種是強調 syntax, * 和 p 都是 "declarator" 的一部份。
int 則是 "type specifier" 的一部份,C 和 C++ 的 syntax
分類的定義都如此。
: 似乎用第一種寫法的人比較多,很多 C++ 大師都是如此。
: 我個人是比較習慣第二種寫法,原因是當有兩個以上的指標:
: T *p1, *p2;
: 第二種寫法顯然比較合理,這時如果這樣寫:
: T* p1, p2;
: 那 p2 就不是指標而是物件了。
以下連結是真正的 C++ 大師(也就是 C++ 發明者本人啦)的說明,
為什麼他個人採用 T* p; 的寫法,他也提到了相反立場者所持包括
上面引文的理由。
http://www.research.att.com/~bs/bs_faq2.html#whitespace
: 個人認為第二種寫法的最大好處,就是便於理解:
我個人是 T* p; 派的,下面這些例子,採用 T* p; 的寫法,
對我來說,反而能看得更清楚。
: 例如(一律由右往左看):
: T *p; // p 是一個指標,指向一個型別 T 的物件
: T &r; // r 是一個 reference,參用一個型別 T 的物件
: 又(同樣一律由右往左看):
: T *f(); // f 回傳一個指標,指向型別 T 的物件
: T &g(); // g 回傳一個 reference,參用一型別 T 的物件
: 又(同樣一律由右往左看):
: T *const p; // p 是一個 const 指標,指向型別 T 的物件
: T const *p; // p 是一個指標,指向型別 T 的 const 物件
: T const *const p; // p 是一個 const 指標,指向型別 T 的 const 物件
: const T *const p; // 同上(只要保持由右往左讀的習慣,就不會昏頭弄錯)
: 甚至(還是由右往左看):
: T *const f(); // f 回傳一個 const 指標,指向型別 T 的物件
: T const &g(); // g 回傳一個 reference,參用一個型別 T 的 const 物件
: T *&h(); // h 回傳一個 reference to pointer,參用一指標,該指標指向
: // 一型別 T 的物件
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Fri Aug 19 22:21:05 2005
※ 引述《gocpp (cpp)》之銘言:
: 一般有幾種習慣:
: T* p; // 向型別 T 看齊
: T *p; // 向變量 p 看齊
: T * p; // 不偏不倚
個人比較習慣 T* p;
理由是在「視覺上」對於「型別的識別」會比較清楚而快速 而且比較不會誤看
: 似乎用第一種寫法的人比較多,很多 C++ 大師都是如此。
: 我個人是比較習慣第二種寫法,原因是當有兩個以上的指標:
: T *p1, *p2;
: 第二種寫法顯然比較合理,這時如果這樣寫:
: T* p1, p2;
: 那 p2 就不是指標而是物件了。
我會儘量避免合在一起寫 而改成:
T* p1;
T* p2;
: 個人認為第二種寫法的最大好處,就是便於理解:
: 例如(一律由右往左看):
: T *p; // p 是一個指標,指向一個型別 T 的物件
: T &r; // r 是一個 reference,參用一個型別 T 的物件
: 又(同樣一律由右往左看):
: T *f(); // f 回傳一個指標,指向型別 T 的物件
: T &g(); // g 回傳一個 reference,參用一型別 T 的物件
: 又(同樣一律由右往左看):
: T *const p; // p 是一個 const 指標,指向型別 T 的物件
: T const *p; // p 是一個指標,指向型別 T 的 const 物件
: T const *const p; // p 是一個 const 指標,指向型別 T 的 const 物件
: const T *const p; // 同上(只要保持由右往左讀的習慣,就不會昏頭弄錯)
: 甚至(還是由右往左看):
: T *const f(); // f 回傳一個 const 指標,指向型別 T 的物件
: T const &g(); // g 回傳一個 reference,參用一個型別 T 的 const 物件
: T *&h(); // h 回傳一個 reference to pointer,參用一指標,該指標指向
: // 一型別 T 的物件
由左往右讀也可以 尤其是以中文思考的時候
int p;
int p
int* p;
int 的指標 p
int& p;
int 的參考 p
int const * p;
int constant 的指標 p ( constant 解讀成名詞:常數 )
int 常數的指標 p
int* const p;
int 指標的常數 p
int const * const p;
((int 常數) 指標) 的常數 p
int* p[5];
==> int*[5] p; // 以 p 為軸將 [5] 搬到左邊
(int 指標) 的陣列 p
共5個
int* p[5][3];
==> int*[3][5] p;
((int 指標) 的陣列) 的陣列 p
共3個
共5個
int (* p)[5];
==> int[5]* p; // 以 (* p) 為軸
int 陣列的指標 p
習慣由右往左讀的同學別被我誤了
C/C++ 本身就是一種語言
能直接解讀程式本身是最好的 不必翻成英文或中文解讀
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.228.217.108
※ 編輯: renderer 來自: 61.228.217.108 (08/19 22:26)
※ 編輯: renderer 來自: 61.228.217.108 (08/19 22:30)
> -------------------------------------------------------------------------- <
作者: UNARYvvv (有趣生活) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Fri Aug 19 23:12:24 2005
※ 引述《gocpp (cpp)》之銘言:
: 一般有幾種習慣:
: T* p; // 向型別 T 看齊
: T *p; // 向變量 p 看齊
: T * p; // 不偏不倚
我習慣用 T *p;
而對型別的辨認,因為我的解讀是看到 *p 先知道 p 是個指標
然後再往回找它指向什麼
而且有時候不只一個指標變數的時候
我可能也會用 T *p1, *p2; 寫在同個 statement 而不是兩個
用到現在也就是都這樣寫了
也由於習慣,所以在閱讀上也並未覺得麻煩
以前是看
The C Programming Language & C++ Primer 這兩本書
分別作為學習 C/C++ 的入門書
裡面的 code 也是用 char *p; 這樣
C++ Primer 有特別提到要注意這點 (忘記 K&R 有沒有)
然後我認同了(偏好) T *p; 這種 * 號靠著變數名的寫法
到現在習慣也就是這樣了。好像跟前面幾位都不同XD
題外話
講到這個就想起以前修 OOP (其實內容是在教 C++ 語言) 的課時
某次上機考,老師出一個 binary tree 的題目
代表 node 的 structure 如下:
struct TreeNode {
TreeNode* left,right;
}
然後一些對宣告指標相關語法不太熟的同學
每次編譯的時候就都會發現
為什麼建立 tree 或是做 traversal 的程式碼
總是往左的可以,而往右的部分總是有很奇怪的錯誤.....
: 似乎用第一種寫法的人比較多,很多 C++ 大師都是如此。
: 我個人是比較習慣第二種寫法,原因是當有兩個以上的指標:
: T *p1, *p2;
: 第二種寫法顯然比較合理,這時如果這樣寫:
: T* p1, p2;
: 那 p2 就不是指標而是物件了。
: 個人認為第二種寫法的最大好處,就是便於理解:
: 例如(一律由右往左看):
: T *p; // p 是一個指標,指向一個型別 T 的物件
: T &r; // r 是一個 reference,參用一個型別 T 的物件
: 又(同樣一律由右往左看):
: T *f(); // f 回傳一個指標,指向型別 T 的物件
: T &g(); // g 回傳一個 reference,參用一型別 T 的物件
: 又(同樣一律由右往左看):
: T *const p; // p 是一個 const 指標,指向型別 T 的物件
: T const *p; // p 是一個指標,指向型別 T 的 const 物件
: T const *const p; // p 是一個 const 指標,指向型別 T 的 const 物件
: const T *const p; // 同上(只要保持由右往左讀的習慣,就不會昏頭弄錯)
: 甚至(還是由右往左看):
: T *const f(); // f 回傳一個 const 指標,指向型別 T 的物件
: T const &g(); // g 回傳一個 reference,參用一個型別 T 的 const 物件
: T *&h(); // h 回傳一個 reference to pointer,參用一指標,該指標指向
: // 一型別 T 的物件
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.70.137.117
> -------------------------------------------------------------------------- <
作者: tomex (tomex_ou) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Sat Aug 20 23:10:54 2005
C#廢了指標,而用ref變數來取代
強型別的時代是趨勢,也是避免糊模不清的治本方法。
C++喜歡用同個關鍵字代表不同的意義
例如*代表是指標,也代表取值子
對於宣告來說,我是覺得*該偏在type那邊,而不該偏在變數。
重型別的人,將來到java或c#等強型別的語言
是比較容易轉化的。
有人說:
int* p1, p2; // p2不是指標
以完全不會語法的人,很容易聯想這語法是要造2個指標的意思
那麼問題並不在於否認人的直觀看法
而是compiler該去修正這樣的宣告誤解才對。
我是從高階語言往低階去學習的
往往能了解高階語言在語意上就是要解決以前不清模糊的地方
或許無法改變低階的現況
但我們學習到新的思想,即使現況作不到,也該堅持正確的直覺宣告法。
compiler並非永遠不標,標準也非永遠不變
而科技始終來自人性,人的直觀法才是取決一切的考量。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.119.52.211
> -------------------------------------------------------------------------- <
作者: clifflu (缺錢啦 @@) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Sat Aug 20 23:40:05 2005
※ 引述《tomex (tomex_ou)》之銘言:
: 有人說:
: int* p1, p2; // p2不是指標
: 以完全不會語法的人,很容易聯想這語法是要造2個指標的意思
: 那麼問題並不在於否認人的直觀看法
: 而是compiler該去修正這樣的宣告誤解才對。
這我就想到一個很好的例子.
在 VB 6.0 中, 如果你使用 Dim Var1, Var2 as String
的話, 你會得到 Var1 (Variant), Var2 (String)
(VB 6.0 的 Variant 是種很神妙的型別, 功能和 C: void 或 VB.NET Object 相近)
然而這樣的寫法在 VB.Net 中做了修正,
也就是會將 Var1 和 Var2 的的型態皆設定為 String.
這確實就是 compiler 向某種使用者 "可能" 的習慣作修正.
然而在反面來看, 將 Dim Var1, Var2 as String
^^^^^^^^^^^^^^
後區視為一個整體, 而前面則是使用預設型別也是有它的道理在.
由此而論, VB.Net 將 Var1, Var2 來視為一個整體反而才是異端邪說了.
所以雖然這樣的寫法可能會比較快, 比較省, 比較優雅, 或甚至有千百種其他的優點,
當一段 code 潛在會被誤認 (ambiguous) 時, 這些寫法都 *應當* 要被其他較不易
出錯, 不容易被誤認, 而能正確執行的碼取代.
畢竟程式碼是給人看的.
--
鬼壓床怎麼辦
騎上去啊
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.212.129
> -------------------------------------------------------------------------- <
作者: khoguan (Khoguan Phuann) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Sun Aug 21 10:16:02 2005
※ 引述《tomex (tomex_ou)》之銘言:
: C++喜歡用同個關鍵字代表不同的意義
: 例如*代表是指標,也代表取值子
C/C++ 關鍵字一字多用的情形,一個明顯的例子就是 static.
在 C 的時代,當他出現在 local scope 的變數宣告前面時,
代表的是 static storage class, 這是 static能夠讓人顧名
思義的用法。但是當它出現在 file scope 的變數宣告前面時,
卻又代表了 internal linkage, 和 static 這個名字難以產生
聯想(file scope 的變數不加 static 本來就已經是 static
storage 了,加上 static 對 static storage 並無影響)。
當初如果多個 intern 關鍵字來表示,似乎還比較好。還可以
和 extern 做對比。但 extern 的用法本身似乎也有問題,而且
C++ 的 extern 除了 scope linkage 的用法,還多了 language
linkage的用法,就是 extern "C" 這種東東 ..Orz..
到了 C++ 時代,為了相容,上述用法仍然承襲下來,但是 C++
標準,已將上述第二種用法標為 deprecated 要人避免使用。
可是另一方面,C++ 又加入了 static 的第三種用法,放在
class member(包含 data 和 function)的宣告前面,表示
它是屬於 class 的 member, 而非屬於個別 class object
的 member. 這和 static 的聯想性也很模糊 ..Orz..
至於 C++ 所 deprecate 的第二種用法,在 C++ 裡是建議宣告
在 unnamed namespace 來取代。
/* internal.c */
static int internal;
// internal.cpp
namespace {
//...
int internal;
}
這種 unnamed namespace 似乎很少人想去利用。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Sun Aug 21 11:33:40 2005
關於指標記號 * 的位置
在這個地方:
unsigned int value;
int* v = (int*) &value;
~~~~~~
int* 是個型別 所以好像 * 向型別靠比較好
但在這個地方:
void (*fun_ptr) ();
~~~~~~~~~~
fun_ptr 是個指標 所以好像 * 向變數靠比較好
呵呵 一笑
看來向哪邊靠似乎都不會有一個比較統一的標準思維
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.228.217.108
※ 編輯: renderer 來自: 61.228.217.108 (08/21 11:34)
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Sun Aug 21 11:42:13 2005
又想到一些例子
int* const value; // 向型別靠好 向變數沒得靠
int (*value)[10]; // 向變數靠好 向型別沒得靠
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.228.217.108
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [討論] 關於指標記號 * 的位置
時間: Sun Aug 21 16:55:55 2005
「T* d」 說不清楚的例子:
int *data0, *data1;
「T *d」 說不清楚的例子:
int* data[2];
C++ 的變數宣告語法是強調 usage 而不是 type
例如:
int * data [3][5];
其 usage 修飾強度順序是:
int * data [3][5];
4 3 0 1 2
所以使用時:
data 的型別是 int * [3][5]
data[0] 的型別是 int * [5]
data[0][1] 的型別是 int *
*data[0][1] 的型別是 int
又例如:
void (*fun_ptr) (int, int);
使用時:
fun_ptr 的型別是 void (*) (int, int)
*fun_ptr 的型別是 void () (int, int)
強調 usage 的宣告語法暗示了我們要怎麼去使用變數
基於這一點寫 int *data; 是合理的
因為 *data 代表 int 而讓 * 靠著 data 似乎滿好的
然而強調 type 的宣告方式似乎也滿自然的
如果使用
型別 變數;
這樣子的宣告格式 會讓我們清楚地知道變數的型別
而在 型別轉換 與 new 的使用時 會得到一個型別清晰的方便性
如:
int* data;
data = (int*) value;
與
int** data;
data = new int*;
基於這點:想清楚地表達型別
而讓 * 靠著型別似乎也是出乎天性
語言本身似乎無意讓 * 偏靠哪一邊
而人卻有心要讓 * 偏靠哪一邊
畢竟
int * data;
的宣告似乎多用了個 ' '
要少用一個 ' '
不靠型別 就得靠變數了
----------------- 以下是閒談 ------------------
小弟個人目前的結論是:
看哪樣子好看、清楚,就那麼靠吧;都不好看的話,就都不靠啦。
如:
int *data0, *data1;
int* data[2];
int const * const data;
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.228.217.108