Re: [问题] 索引值的型态

楼主: uranusjr (←這人是超級笨蛋)   2014-10-03 21:46:18
※ 引述《bjiyxo (若自礌)》之铭言:
: 如题
: 因为曾听过不同型态的变量做运算的时候
: 会增加电脑的负担
: 而索引值又常常用到
: 所以好奇想问
: 索引值的默认型态是什么?
→ 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。
楼主: uranusjr (←這人是超級笨蛋)   2013-10-02 18:52:00
其实只要是整数形态都差不多, 如果你坚持一定要挑一个,就用 ptrdiff_t 吧
作者: wowslr (平凡姜太公)   2013-10-02 19:44:00
container 用里面的 size_type, 不然就 size_t?
作者: Killercat (杀人猫™)   2013-10-03 15:52:00
STL里面(或者说C++ Libs)都用size_tC就没有一定标准了 typedef/#define满天飞的....另外 size_t通常是long或者uint64(两者大小一样)
作者: LPH66 (-6.2598534e+18f)   2014-10-03 22:10:00
个人觉得选 size_t 的原因是出自“索引值”的语意ptrdiff_t 比较属于“索引值的差”这个语意
作者: bjiyxo (若自礌)   2014-10-04 00:08:00
感谢您长篇的详细回答,我可以理解成因为索引值可以是负的所以型态应该是ptrdiff_t
作者: Killercat (杀人猫™)   2014-10-04 04:22:00
这其实是STL一个长久以来的legacy issue...size_t被广泛用在包含std::string::find这些地方但是如你所说 那我要表示-1怎么办?std::string就引入了一个叫做std::string::npos的常数 他是((uint)-1) XD只能说这似乎是将错就错的一种做法就是....所以std::string::find会传回一些debugger上根本难以理解的东西 反正,它就叫做npos XD这个我想uranusjr应该也很清楚 只是当作故事说给其他可能没听过这件事的人参考一下就是 :Phttp://tinyurl.com/84ne58c 算C++的历史包袱吧
作者: Feis (永远睡不着 @@)   2014-10-04 04:28:00
nonsense
楼主: uranusjr (←這人是超級笨蛋)   2014-10-05 01:58:00
觉得是 nonsense 就讲点 sense 出来, 不要只会嘴啊 ^_<
作者: carylorrk (carylorrk)   2014-10-05 03:15:00
K大提的那个是否可以用 boost::optional 解决?其实用非负整数作为索引值新手最容易犯的错是for(size_t idx = LEN; idx > 0; --idx) 这样吧XD
作者: Killercat (杀人猫™)   2014-10-05 13:56:00
可以这样说没错,所以find回来的值不能直接for XD不过很玄妙的是 STL绝大多数的library(有例外)比方说std::copy, std::transform, std::for_each都可以正确的handle string::npos(用iterator先包一层就没这问题)早期的if系列某些实作会因为这些爆掉 如std::enable_if当然现在应该没有错误的了... 再错这STL也没人用了 XD
作者: Feis (永远睡不着 @@)   2014-10-05 22:51:00
指标相减有可能是未定义行为. 这推导的前提不完整基本上阵列到底能有多大跟 ptrdiff_t 的范围之类的硬要选 ptrdiff_t 当然是比较好. 但我觉得这问题本身nonsensopreator+ 跟 operator- 是否是真的反运算也是该讨论的看不出 c = a + i 跟 i = c - a 的绝对关系. 可能是我想错有没有可能 a[i] 存在但是 c - a 的结果不存在呢 ?要想想 size_t 跟 ptrdiff_t 之间是实作相依ptrdiff_t 是 "相减" 的结果. 而 "加" 的对象只需要是整数加完之后还落在阵列内就是合法的.看不出来 "加" 的整数只能是 ptrdiff_t 的必然性.我好像有表达障碍. 抱歉. 喝酒不推文. 推文不喝酒 : (简言之就是 sizeof(ptrdiff_t) < sizeof(size_t) 时就怪怪的我的看法就是索引值是整数型别. It's all重点是这个整数会不会落在阵列内才是我们应该关心的ptrdiff_t 并不能保证你会存取到你要的元素

Links booklink

Contact Us: admin [ a t ] ucptt.com