我使用-1作为返回类型为size_t(无符号类型)的函数的标志值。
我一开始并没有注意到它,特别是因为它没有导致我的代码出现任何错误(我用x == -1检查它,而不是x< 0)。
是否有任何微妙的原因我不应该保留原样?什么时候这可能出乎意料?这是常用的吗?
ptrdiff_t不常见,输入时间更长,无论如何它都不是合适的类型,因为函数会将索引返回到数组中。
答案 0 :(得分:13)
-1
将始终转换为最大无符号值,这是由于4.7
部分转换部分所致:
如果目标类型是无符号的,则结果值是与源一致的最小无符号整数 整数(模2n,其中n是用于表示无符号类型的位数)。 [注意:在两个 补码表示,这种转换是概念性的,并且位模式没有变化(如果有的话) 不是截断)。 - 后注]
C99 的相同引用来自6.3.1.3
:
否则,如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值 直到该值在新类型的范围内。 49)
所以我们最终得到:
-1 + (UMAX + 1)
是:
UMAX
答案 1 :(得分:3)
明显的警告在于一组元素的大小等于可能的最大大小。这种情况在实践中发生的可能性和可用性实际上是导致问题的原因可以忽略不计。
如果您查看C ++ std::string
类,您会注意到static std::string::npos
数据成员被定义为完全-1
转换为std::string::size_type
(实际上只是{{} 1}}。这使得这种“技术”具有优先感,这使得它能够完善最低惊喜原则™,这一直是一件好事。
现在,在比较中直接使用std::size_t
就是在寻找麻烦。您应该像-1
一样确保该值具有可访问的名称,以确保其特殊含义。遗憾的是,C ++类型系统对此不够严格,以防止用户在脚下射击自己,但至少一个坚持记录在案的最佳实践的用户不会想到以不同的方式做事。
答案 2 :(得分:2)
在试图想出这可能出错的方法之后,我意识到调用函数可能隐式地将返回值强制转换为更大的类型(即unsigned int到unsigned long long)存在危险。然后检查该值== -1是否为假。
更安全的选择是明确使用size_t.max作为sentinel值。在签名和未签名类型之间进行更改时,我总是感到不舒服。有时我认为更合理的方法就是让所有内容都签名(就像Java一样)。