3

What if I have something like this:

int a = 20;
int min = INT_MIN;

if(-a - min)
//do something

Assume that INT_MIN if positive is more than INT_MAX. Would min ever be converted by the compiler to something like -min as in -INT_MIN, which could be undefined?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
user2672807
  • 1
  • 2
  • 7
  • 20
  • possible duplicate of [C++ underflow and overflow](http://stackoverflow.com/questions/10011372/c-underflow-and-overflow) – Jonathan Potter Sep 25 '13 at 21:24
  • The identifier "`min`" has a halfway decent chance of shadowing `std::min` (when there's a `using` statement), so I'd recommend against using it. – Brian Cain Sep 25 '13 at 21:32
  • 1
    @JonathanPotter I think that the OP of this question understands perfectly that signed arithmetic overflow is undefined (which is the answer to the question you suggest), and is simply worried that an apparently defined binary subtraction could be interpreted as an undefined unary minus. – Pascal Cuoq Sep 25 '13 at 21:32
  • @Brian I do use `using namespace std;` but I don't understand how min() would be called if I am not using parentheses. – user2672807 Sep 25 '13 at 21:36
  • @user2672807: he didn't say `min` would be called, he said that your variable shadows it. So if you try to call `min` without qualifying it then you can't, because `min` means the `int` not the function. – Steve Jessop Sep 25 '13 at 21:37
  • @Steve I'm ok with that, but is it considered bad practice? – user2672807 Sep 25 '13 at 21:39
  • @user2672807: considered bad by whom? It's pretty safe in this case because you can't call an `int` -- hiding a standard function with a function would be riskier. Personally I consider `using namespace std;` worse than hiding a name, so the issue of unexpected hiding shouldn't really arise to begin with. – Steve Jessop Sep 25 '13 at 21:43
  • @BrianCain - there's no chance of an identifier `min` conflicting with `std::min` in correctly written code; that's why we have namespaces. Blowing them away with `using namespace std;` is an abomination. – Pete Becker Sep 26 '13 at 00:18
  • @PeteBecker, the world is littered with incorrectly written code. Abomination or no, it happens and my recommendation stands. – Brian Cain Sep 26 '13 at 03:56
  • @BrianCain - `using namespace std;` is simply wrong, and the best protection against it is to not do it. Given the choice of not using `min` as a name and not using `using namespace std;`, the latter is obviously better. Especially when the issue is not that `min` conflicts with `std::min`, but that **if** you use `min` as a variable name **and** you call `std::min` without a qualifier you'll get an error. That error is simple to fix; if you can't bring yourself to remove `using namespace std;`, then add a qualifier to `min` where it's called. – Pete Becker Sep 26 '13 at 13:57
  • @PeteBecker, I think you're confused about my recommendation. I agree with everything you said. But it's a false dichotomy. I'm suggesting that one avoid use of `min` because of the popularity of `using namespace std` (or even `using std::min`, which I suppose you might not have as much of a problem with). Many of us collaborate our authorship of program code with others who are not as attentive and in order to avoid the opportunity for head-scratching, let's just avoid the problem entirely. – Brian Cain Sep 26 '13 at 22:39
  • @BrianCain - I'm not confused at all. – Pete Becker Sep 26 '13 at 23:44
  • @PeteBecker, "[Well, it's good that you're fine and I'm fine](http://www.youtube.com/watch?v=VEB-OoUrNuk#t=29s)" ;) – Brian Cain Sep 27 '13 at 02:54

2 Answers2

2

You are right that unary minus applied to INT_MIN can be undefined, but this does not happen in your example.

-a - min is parsed as (-a) - min. Variable min is only involved in binary subtraction, and the first operand only needs to be strictly negative for the result to be defined.

If the compiler transforms the subtraction to something else, it is its responsibility to ensure that the new version always computes the same thing as the old version.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • So it's basically the same as `min + a`? – user2672807 Sep 25 '13 at 21:32
  • @user2672807 It is the same as `-(min + a)` when neither version overflows. I cannot seem to find values for which one causes an overflow but not the other, but I cannot say that there aren't (yet). – Pascal Cuoq Sep 25 '13 at 21:35
  • 2
    @PascalCuoq: Assuming `x` is an `int`, and assuming 2's complement: `-x` overflows if and only if `x` is `INT_MIN`. `INT_MIN + x` overflows if and only if `x` is strictly negative. So `-(INT_MIN + x)` overflows if and only if `x` is strictly negative or zero. Meanwhile `- x - min` overflows if and only if `-x` overflows or is not strictly negative. That is to say, if and only if `x` is zero or negative. So you are correct, the overflow conditions are the same. – Steve Jessop Sep 25 '13 at 23:03
  • @SteveJessop any chance for pointing to the std "justifying" your (proven to be right) claim? – Shmil The Cat Nov 19 '22 at 23:33
  • 1
    @Shmil: I think my "proof" only relies on the ranges of 2's complement arithmetic: specifically that the absolute value of INT_MIN is one greater than INT_MAX (that's absolute value computed in real-world mathematics, of course, not in the arithmetic of the integer type). That's the reason for my claim that -x overflows if and only if x is INT_MIN. No doubt those limits are stated or implied in the current version of the standard somewhere, but sorry, I'm not going looking for it :-) – Steve Jessop Nov 23 '22 at 12:31
1

The result of x - y is defined as the mathematical result of subtracting y from x. If the mathematical result can be represented in the result type (int in this case), then there is no overflow.

A compiler is free to transform the expression in any way it likes, such as by changing

x - y

to

x + (-y)

but only if the transformation keeps the same behavior in cases where the original behavior is well defined. In the case of y == INT_MIN, it can still perform the transformation as long as the undefined behavior of evaluating -INT_MIN yields the same end result (which it typically will).

To answer the question in the title:

Is INT_MIN subtracted from any integer considered undefined behavior?

INT_MIN - INT_MIN == 0, and cannot overflow.

Incidentally, I think you mean int rather than "integer". int is just one of several integer types.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631