C++核心准则ES.106:不要试图通过使用无符号类型避免负值

ES.106: Don't try to avoid negative values by using unsigned

ES.106:不要试图通过使用无符号类型避免负值

 

Reason(原因)

Choosing unsigned implies many changes to the usual behavior of integers, including modulo arithmetic, can suppress warnings related to overflow, and opens the door for errors related to signed/unsigned mixes. Using unsigned doesn't actually eliminate the possibility of negative values.

选择无符号数意味着修改整数的很多无用行为(如含按模运算),这会抑制溢出关联的警告信息,为有符号/无符号数混合计算相关的错误打开了大门。使用无符号数不会真的消除负值的可能性。

 

Example(示例)

unsigned int u1 = -2;   // Valid: the value of u1 is 4294967294
int i1 = -2;
unsigned int u2 = i1;   // Valid: the value of u2 is 4294967294
int i2 = u2;            // Valid: the value of i2 is -2

These problems with such (perfectly legal) constructs are hard to spot in real code and are the source of many real-world errors. Consider:

在实际的代码中,这些(完全合法的)构造中的隐含的问题很难发现,会带来很多现实世界中的错误。考虑下面的代码:

unsigned area(unsigned height, unsigned width) { return height*width; } // [see also](#Ri-expects)
// ...
int height;
cin >> height;
auto a = area(height, 2);   // if the input is -2 a becomes 4294967292

Remember that -1 when assigned to an unsigned int becomes the largest unsigned int. Also, since unsigned arithmetic is modulo arithmetic the multiplication didn't overflow, it wrapped around.

记住当-1赋给一个无符号整数时,会变成一个最大的无符号整数。同时,由于无符号数学运算是按模运算,乘法运算不会溢出,而是发生回绕。

 

Example(示例)

unsigned max = 100000;    // "accidental typo", I mean to say 10'000
unsigned short x = 100;
while (x < max) x += 100; // infinite loop

Had x been a signed short, we could have warned about the undefined behavior upon overflow.

如果x是一个有符号短整数,我们会收到一个由于溢出而导致无定义行为的警告。

 

Alternatives(其他选项)

  • use signed integers and check for x >= 0

  • 使用有符号整数并检查x是否大于0

  • use a positive integer type

  • 使用一个正整数类型

  • use an integer subrange type

  • 使用值域限定的整数类型

  • Assert(-1 < x)

  • 使用断言检查(-1

 

For example(示例)

struct Positive {
    int val;
    Positive(int x) :val{x} { Assert(0 < x); }
    operator int() { return val; }
};

int f(Positive arg) { return arg; }

int r1 = f(2);
int r2 = f(-2);  // throws

 

Note(注意)

???

 

Enforcement(实施建议)

See ES.100 Enforcements.

参考ES.100的实施建议。

 

原文链接

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es106-dont-try-to-avoid-negative-values-by-using-unsigned

 


 

新书介绍

以下是本人3月份出版的新书,拜托多多关注!

 

本书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。

 

觉得本文有帮助?欢迎点赞并分享给更多的人。

阅读更多更新文章,请关注微信公众号【面向对象思考】

你可能感兴趣的:(C++,C++,核心准则,无符号,负值)