Cas*_*sey 4 c++ unsigned signed
最近,在重构过程中,我正在查看我编写的一些代码并注意到以下几点:
unsigned char在区间[0-255]中强制执行值的函数.int或long具有if语句内部语句的数据类型,以静默方式将值钳位到有效范围.upper bound,但已知的和明确的非负lower bound被宣布为unsigned数据类型(int或long取决于可能性的是,upper bound去上述40亿).不一致是令人不安的.这是一个很好的做法,我应该继续吗?我应该重新考虑逻辑并坚持使用int或long使用适当的非通知钳位?
关于使用"适当"的注释:有些情况下我使用signed数据类型并在值超出范围时抛出通知异常,但这些是为divde by zero和保留的constructors.
在C和C++中,有符号和无符号整数类型具有某些特定的特征.
签名类型的界限远远不为零,超出这些界限的操作具有未定义的行为(或者在转换的情况下实现定义).
无符号类型的下限为零,上限远离零,超过这些边界的操作会悄然环绕.
通常你真正想要的是一个特定的值范围,当操作超过这些边界时(饱和,发出错误信号等),会有一些特定的行为.有符号或无符号类型都不完全适合这些要求.混合有符号和无符号类型的操作可能会令人困惑; 这种操作的规则是由语言定义的,但它们并不总是很明显.
无符号类型可能会有问题,因为下限为零,因此具有合理值(无法接近上限)的操作可能会以意外的方式运行.例如,这个:
for (unsigned int u = 10; u >= 0; u --) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
是一个无限循环.
一种方法是将签名类型用于不绝对需要无符号表示的所有内容,选择足够宽的类型来保存所需的值.这避免了签名/无符号混合操作的问题.例如,Java通过不使用无符号类型来强制执行此方法.(就个人而言,我认为这个决定是过度的,但我可以看到它的优点.)
另一种方法是对逻辑上不能为负的值使用无符号类型,并且对可能下溢或混合有符号和无符号类型的表达式要非常小心.
(另一个是用你想要的行为来定义你自己的类型,但是这有成本.)
正如John Sallay的回答所说,一致性可能比你采取的特定方法更重要.
我希望我能给出"这种方式是正确的,那种方式是错误的"答案,但确实没有一种.
我可能会认为一致性是最重要的。如果您选择一种方法并正确执行,那么其他人稍后就会很容易理解您在做什么。关于正确行事,有几个问题需要考虑。
首先,检查整型变量 n 是否在有效范围内(例如 0 到 N)时很常见:
if ( n > 0 && n <= N ) ...
Run Code Online (Sandbox Code Playgroud)
仅当 n 带符号时此比较才有意义。如果 n 是无符号的,那么它永远不会小于 0,因为负值会环绕。您可以将上面的内容重写为:
if ( n <= N ) ...
Run Code Online (Sandbox Code Playgroud)
如果有人不习惯看到这一点,他们可能会感到困惑并认为你做错了。
其次,我要记住,C++ 中的整数类型大小没有保证。因此,如果您希望某些内容以 255 为界,则 unsigned char 可能无法达到目的。如果变量具有特定含义,那么使用 typedef 来表明这一点可能很有价值。例如,size_t 是与内存地址一样宽的值。这意味着您可以将它与数组一起使用,而不必担心在 32 位或 64 位计算机上使用。我尝试尽可能使用此类 typedef,因为它们清楚地传达了我使用该类型的原因。(size_t 因为我正在访问一个数组。)
第三,回到环绕问题。您希望使用无效号码发生什么情况。对于 unsigned char,如果您使用该类型来绑定数据,那么您将无法检查是否输入了超过 255 的值。这可能是问题,也可能不是问题。
| 归档时间: |
|
| 查看次数: |
2113 次 |
| 最近记录: |