From 14ef2cde84e4c3529bbc91d41946eb63fd92dbbe Mon Sep 17 00:00:00 2001 From: Bjarne Stroustrup Date: Thu, 18 May 2017 16:45:10 -0400 Subject: [PATCH] add rules against use of unsigned addresses #571 --- CppCoreGuidelines.md | 124 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index 47c03b0..f666e40 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -1,6 +1,6 @@ # C++ Core Guidelines -May 16, 2017 +May 18, 2017 Editors: @@ -1533,6 +1533,10 @@ Once language support becomes available (e.g., see the [contract proposal](http: `Expects()` can also be used to check a condition in the middle of an algorithm. +##### Note + +No, using `unsigned` is not a good way to sidestep the problem of [ensuring that a value is nonnegative](#Res-nonnegative). + ##### Enforcement (Not enforceable) Finding the variety of ways preconditions can be asserted is not feasible. Warning about those that can be easily identified (`assert()`) has questionable value in the absence of a language facility. @@ -9310,6 +9314,8 @@ Arithmetic rules: * [ES.103: Don't overflow](#Res-overflow) * [ES.104: Don't underflow](#Res-underflow) * [ES.105: Don't divide by zero](#Res-zero) +* [ES.106: Don't try t avoid negative values by using `unsigned`](#Res-nonnegative) +* [ES.107: Don't use `unsigned` for subscripts](#Res-subscripts) ### ES.1: Prefer the standard library to other libraries and to "handcrafted code" @@ -11875,6 +11881,122 @@ This also applies to `%`. * Flag division by an integral value that could be zero + +### ES.106: Don't try to avoid negative values by using `unsigned` + +##### 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; // OK: the value of u1 is 4294967294 + int i1 = -2; + unsigned int u2 = i1; // OK: the value of u2 is -2 + int i2 = u2; // OK: 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 arithmentic the multiplication didn't overflow, it wrapped around. + +##### Example + + unsigned max = 100000; // "accidental typo", I mean to say 10'000 + unsigned short x = 100; + while (x= 0` +* use a positive integer type +* use an integer subrange type +* `Assert(-1ES.107: Don't use `unsigned` for subscripts + +##### Reason + +To avoid signed/unsigned confusion. +To enable better optimization. +To enable better error detection. + +##### Example, bad + + vector vec {1,2,3,4,5}; + + for (int i=0; i::size_type i=0; i + struct My_container { + public: + // ... + T& operator[](int i); // not unsigned + // ... + }; + +##### Example + + ??? demonstrate improved code generation and potential for error detection ??? + +##### Alternatives + +Alternatives for users + +* use algorithms +* use range-for +* use iterators/pointers + +##### Enforcement + +Very tricky as long as the standard-library containers get it wrong. + # Per: Performance ??? should this section be in the main guide???