它是使用无符号的数据类型来执行非负和/或有效值的最佳做法?(Is it a best practic

2019-09-17 04:39发布

最近,重构会议期间,我一直在寻找了一些代码,我写了,发现几件事情:

  1. 我有使用的功能unsigned char在区间[0-255]强制值。
  2. 其他功能中使用intlong数据类型与if函数内声明以静默夹紧值有效范围。
  3. 包含在类和/或声明为参数到具有函数的值未知的upper bound ,但已知的和明确的非负lower bound被宣布为unsigned数据类型( intlong取决于该可能性 upper bound去上述40亿)。

不一致性也令人担忧。 这是一个很好的做法,我应该继续? 我应该重新思考逻辑,坚持使用intlong使用适当的非通知夹紧?

对使用“适当”的注意事项:有,我使用的情况下signed的数据类型和抛出异常通知当值超出范围,但这些被保留用于divde by zeroconstructors

Answer 1:

我可能会认为,一致性最重要的。 如果你选择一个方式做正确那么这将是容易被别人理解你在以后的某个时间在做什么。 就说明这样做是正确的,有几个问题需要考虑。

首先,它是常见的,当检查是否一个整数变量n处于有效范围内,说0到N写:

if ( n > 0 && n <= N ) ...

如果n签订这种比较才有意义。 如果n是无符号的那么它将永远不会小于0,因为负值将环绕。 你可以把上面的,如果像刚才:

if ( n <= N ) ...

如果有人不看惯了这一点,他们可能会感到困惑,并认为你没有错。

其次,我会记住,没有在C ++整数无类型大小的保证。 因此,如果你想要的东西通过255为界,无符号的字符可能不会做的伎俩。 如果变量有特定的含义则可能是有价值的,以一个typedef证明。 例如,为size_t是一个值一样宽的存储器地址。 这意味着你可以用阵列使用它,而不必担心被32吨或64位的机器。 我尝试使用这种类型定义尽可能因为他们清楚地传达为什么我使用的类型。 (size_t型,因为我访问数组)。

三是重新包装的解决这个问题。 你要什么有一个无效的号码发生。 在unsigned char型的情况下,如果您使用绑定的数据类型,那么你将不能够检查是否输入了超过255的值。 这可能会或可能不会是一个问题。



Answer 2:

在C和C ++,符号和无符号整数类型具有一定的具体特性。

签名类型有远从零界限,超出这些边界业务具有不确定的行为(或转换的情况下实现定义)。

无符号类型有一个下限为零并从零上限远,而且操作方面超出界限静静环绕。

通常你真正想要的是一些特定的行为值的特定范围内时,操作超出这些范围(饱和度,发出错误信号,等)。 既未签署也无符号类型是完全适合于这种要求。 和操作组合符号和无符号的类型可能会造成混淆; 对于这样的操作规则是由语言定义的,但他们并不总是显而易见的。

无符号类型可以是问题,因为下界为零,因此操作用合理的值(远不及上限)可以以意想不到的方式表现。 例如,这样的:

for (unsigned int u = 10; u >= 0; u --) {
    // ...
}

是一个无限循环。

一种方法是使用符号类型的一切并不绝对需要一个无符号的表示,选择一个类型的宽度足以您需要的值。 这避免了与无/有符号混合操作方面的问题。 Java中,例如,通过强制执行不具有所有无符号类型这种做法。 (我个人认为,这一决定是大材小用,但我可以看到它的优势。)

另一种方法是使用无符号类型值逻辑上不能为负,并且非常小心,可能下溢表达式或签名的组合和无符号类型。

(另一个是与正是你想要的行为定义自己的类型,但有成本。)

正如约翰Sallay的回答说,一致性可能比其特定的方法,你需要更重要。

我希望我可以给一个“这种方式是正确的,这样是不对的”的答案,但实在是没有一个。



Answer 3:

从最大的好处unsigned是,它记录了你的代码,该值始终为正。

它并不真正买任何安全作为一个无符号的范围之外去通常是无意的,并可能导致同样多的挫折,如果它被签署。

我有使用无符号字符在区间[0-255]强制值的函数。

如果你依靠的回转,然后使用uint8_t作为unsigned char也可能会被超过8位。

其他功能中使用int或长数据类型与如果函数内声明以静默夹紧值有效范围。

这真的是正确的行为?

包含在类和/或声明为参数到具有函数的值未知的上限,但已知的和明确的非负下界被宣布为一个无符号的数据类型(int或长取决于结合的上部去上述40亿的可能性)。

你从哪里得到的上限4,000,000,000而来? 你界是之间INT_MAXINT_MIN (你也可以使用std::numeric_limits在C ++ 11就可以使用。 decltype指定哪个你可以包装成一个模板/宏类型:

decltype(4000000000) x; // x can hold at least 4000000000


Answer 4:

这是一个主观的问题,但我会给你我的起飞。

个人如果没有键入指定的操作我想CARRAY出来,IE的std ::对的size_t尺寸和指数,uintXX_t特定的比特深度等等......然后我默认为无符号的,除非我需要使用负值。

因此,这不是用它来执行正值的情况,而是我必须选择signed明确的功能。

除了这个,我,如果你担心的界限,那么你需要做自己的边界检查,以确保您不会溢出。

但我说,更多的时候则不是你的数据类型将与你将它应用到函数的返回类型的情况下决定的。



文章来源: Is it a best practice to use unsigned data types to enforce non-negative and/or valid values?