→ uranusjr: 其實只要是整數形態都差不多, 如果你堅持一定要挑一個, 10/02 18:52
→ uranusjr: 就用 ptrdiff_t 吧 10/02 18:52
→ wowslr: container 用裡面的 size_type, 不然就 size_t? 10/02 19:44
→ Killercat: STL裡面(或者說C++ Libs)都用size_t 10/03 15:52
→ Killercat: C就沒有一定標準了 typedef/#define滿天飛的.... 10/03 15:53
→ Killercat: 另外 size_t通常是long或者uint64(兩者大小一樣) 10/03 15:55
我想說一下我選 ptrdiff_t 的原因
首先, 根據標準, subscripting 只是指標運算 + dereferencing 的 syntax sugar
也就是對於一個陣列 a 與整數 i(注意這邊都還完全不考慮形態)
a[i]
完全對等於
*(a + i)
這有兩個意義:
1. Subscript 使用的型別應該與 pointer 型別相同
其實我猜 compiler 都會最佳化, 不過如果完全照字面解答原 po 的問題, 那麼
我們要找的應該是 pointer 運算時使用的型別。
2. Subscript 值可以是負的
由於負方向的指標運算完全合法, negative subscript(e.g. a[-1])完全符合
標準, 即使並不直觀。
所以 size_t 並不符合。主要因為它是無號整數, 不過其實也沒人說過它和指標有什
麼關聯。我們要找的是用在指標運算, 且有號的型別:
http://goo.gl/1Xpf6x (www.gnu.org)
Data Type: ptrdiff_t
This is the signed integer type of the result of subtracting two pointers.
For example, with the declaration char *p1, *p2;, the expression p2 - p1
is of type ptrdiff_t. This will probably be one of the standard signed
integer types (short int, int or long int), but might be a nonstandard
type that exists only for this purpose.
延續前面的例子, 假設 a 是 foo 的 array, 且索引取值後的結果是 b:
b = a [ i ]
↑ ↑ ↑
foo foo[] ??
b = *( a + i )
↑ ↑ ↑
foo foo[] ??
令 *c = b, 則
c = a + i
↑ ↑ ↑
foo* foo[] ??
i = c - a 讓 a decay 為指標
↑ ↑ ↑
?? foo* foo*
根據上面的規範, i 的型別顯然應該是 ptrdiff_t。
--
「我最想要的同伴嘛,首先是要笑口常開,其次是我們能永遠不會發生誤會。
如果這些都能辦到的話,嗯,如果他是世界上第一流的橋手,也還不錯。」
-- 班尼多‧加羅素,前義大利藍隊成員
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 218.161.94.175
※ 文章網址: http://www.ptt.cc/bbs/C_and_CPP/M.1412343985.A.BD3.html
推 LPH66: 個人覺得選 size_t 的原因是出自「索引值」的語意 10/03 22:10
→ LPH66: ptrdiff_t 比較屬於「索引值的差」這個語意 10/03 22:10
→ bjiyxo: 感謝您長篇的詳細回答,我可以理解成因為索引值可以是負的 10/04 00:08
→ bjiyxo: 所以型態應該是ptrdiff_t 10/04 00:08
推 Killercat: 這其實是STL一個長久以來的legacy issue... 10/04 04:22
→ Killercat: size_t被廣泛用在包含std::string::find這些地方 10/04 04:23
→ Killercat: 但是如你所說 那我要表示-1怎麼辦?std::string就引入 10/04 04:23
→ Killercat: 了一個叫做std::string::npos的常數 他是((uint)-1) XD 10/04 04:23
→ Killercat: 只能說這似乎是將錯就錯的一種做法就是.... 10/04 04:24
→ Killercat: 所以std::string::find會傳回一些debugger上根本難以 10/04 04:25
→ Killercat: 理解的東西 反正,它就叫做npos XD 10/04 04:25
→ Killercat: 這個我想uranusjr應該也很清楚 只是當作故事說給其他 10/04 04:26
→ Killercat: 可能沒聽過這件事的人參考一下就是 :P 10/04 04:27
→ Feis: nonsense 10/04 04:28
→ uranusjr: 覺得是 nonsense 就講點 sense 出來, 不要只會嘴啊 ^_< 10/05 01:58
→ carylorrk: K大提的那個是否可以用 boost::optional 解決? 10/05 03:15
→ carylorrk: 其實用非負整數作爲索引值新手最容易犯的錯是 10/05 03:16
→ carylorrk: for(size_t idx = LEN; idx > 0; --idx) 這樣吧XD 10/05 03:16
→ Killercat: 可以這樣說沒錯,所以find回來的值不能直接for XD 10/05 13:56
→ Killercat: 不過很玄妙的是 STL絕大多數的library(有例外)比方說 10/05 13:56
→ Killercat: std::copy, std::transform, std::for_each都可以正確 10/05 13:56
→ Killercat: 的handle string::npos(用iterator先包一層就沒這問題) 10/05 13:57
→ Killercat: 早期的if系列某些實作會因為這些爆掉 如std::enable_if 10/05 13:58
→ Killercat: 當然現在應該沒有錯誤的了... 再錯這STL也沒人用了 XD 10/05 13:59
→ Feis: 指標相減有可能是未定義行為. 這推導的前提不完整 10/05 22:51
→ Feis: 基本上陣列到底能有多大跟 ptrdiff_t 的範圍之類的 10/05 22:53
→ Feis: 硬要選 ptrdiff_t 當然是比較好. 但我覺得這問題本身nonsens 10/05 22:55
→ Feis: opreator+ 跟 operator- 是否是真的反運算也是該討論的 10/05 22:56
→ Feis: 看不出 c = a + i 跟 i = c - a 的絕對關係. 可能是我想錯 10/05 23:05
→ Feis: 有沒有可能 a[i] 存在但是 c - a 的結果不存在呢 ? 10/05 23:13
→ Feis: 要想想 size_t 跟 ptrdiff_t 之間是實作相依 10/05 23:17
→ Feis: ptrdiff_t 是 "相減" 的結果. 而 "加" 的對象只需要是整數 10/05 23:22
→ Feis: 加完之後還落在陣列內就是合法的. 10/05 23:23
→ Feis: 看不出來 "加" 的整數只能是 ptrdiff_t 的必然性. 10/05 23:24
→ Feis: 我好像有表達障礙. 抱歉. 喝酒不推文. 推文不喝酒 : ( 10/05 23:27
→ Feis: 簡言之就是 sizeof(ptrdiff_t) < sizeof(size_t) 時就怪怪的 10/05 23:29
→ Feis: 我的看法就是索引值是整數型別. It's all 10/05 23:30
→ Feis: 重點是這個整數會不會落在陣列內才是我們應該關心的 10/05 23:32
→ Feis: ptrdiff_t 並不能保證你會存取到你要的元素 10/05 23:34