9

AFAIK this is a standard "idiom"

#  define INT_MIN   (-INT_MAX - 1)  
#  define INT_MAX   2147483647    

Question: Why is the definition of INT_MIN not as -2147483648?

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • 4
    if you define both of them separately, when you want to do a modification, you have to remind yourself to change both. if one of them relies on the other one, then you can just change one and the change will apply to both. – Jason Hu Sep 23 '14 at 20:12
  • @HuStmpHrrr:I read that there is a reason but there was no explanation of that reason (was related to compilers and not code design) – Cratylus Sep 23 '14 at 20:16
  • unfortunately i don't have gcc with me currently. but i think you can try `int foo = -2147483648;` directly and see if compiler complains. i am curious about the result. – Jason Hu Sep 23 '14 at 20:22
  • 1
    I'm not a big fan of the fact that when I mark it as "possible duplicate" it gets stamped "duplicate" immediately. But anyway, the question has been asked many times before. – AnT stands with Russia Sep 23 '14 at 20:39
  • @AndreyT I concur. It was nice and all that said-power to insta-dupe was granted to those of us with enough insanity to build high-rep, but I would have preferred if they would have given an *option* to old-style nominate it as a duplicate as an alternative if we feel it is one, but would like the extra weight of our fellow members behind it. I wouldn't think it would be a hard feature to add. Maybe something to hurl around on meta. – WhozCraig Sep 23 '14 at 20:59

1 Answers1

16

Because 2147483648 is a long value as it does not fit in an int (in common system with 32-bit int and 64-bit long, on system with 32-bit long it is of type long long). So -2147483648 is of type long, not int.

Remember in C, an unsuffixed decimal integer constant is of the first type int, long or long long where it can be represented.

Also in C -2147483648 is not a integer constant; 2147483648 is an integer constant. -2147483648 is an expression formed with the unary operator - and the integer constant 2147483648.

EDIT: if you are not convinced -2147483648 is not of type int (some people in the comments still seem to doubt), you can try to print this:

printf("%zu %zu\n", sizeof INT_MIN, sizeof -2147483648);

You will most likely end up with:

4 8

on common 32 and 64-bit systems.

Also to follow a comment, I'm talking about recent C Standard: use c99 or c11 dialect to test this. c89 rules for decimal integer constant are different: -2147483648 is of type unsigned long in c89. Indeed in c89 (it is different in c99, see above), a unsuffixed decimal integer constant is of type int, long or unsigned long.

EDIT2: @WhozCraig added another example (but for C++) to show -2147483648 is not of type int.

The following example, though in C++, drives home this point. It was compiled with a 32-bit architecture g++. Note the type info gathered from the passed parameter deduction:

#include <iostream>
#include <climits>

template<typename T>
void foo(T value)
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    std::cout << value << '\n';
}

int main()
{
    foo(-2147483648);
    foo(INT_MIN);
    return 0;
}

Output

void foo(T) [T = long long]
-2147483648
void foo(T) [T = int]
-2147483648
ouah
  • 142,963
  • 15
  • 272
  • 331
  • Sorry I don't understand. This `-2147483648` is considered a `long`? – Cratylus Sep 23 '14 at 20:14
  • 3
    More to the point. unary minus is applied to an *expression*, the type of which has already been established by the *value*. `2147483648` as a value (before applying unary-minus) is not representable as `int` on a 32bit system. – WhozCraig Sep 23 '14 at 20:14
  • 3
    I don't think this is what OP asked, as INT_MIN is defined using INT_MAX, OP's wondering why INT_MIN is not defined by using a constant (like INT_MAX). – Invalid Sep 23 '14 at 20:16
  • @WhozCraig:What you say makes sense – Cratylus Sep 23 '14 at 20:17
  • @Cratylus is what ouah said, just in different words. Same premise. – WhozCraig Sep 23 '14 at 20:18
  • my opinion is this: to the line `int foo = INT_MIN;`, even though it extends to `int foo = -2147483648;`, compiler won't compile the code to `int foo = 2147483648; foo = -foo;`, the code is compiled at once, i.e. compiler parses the AST and directly pass the result to variable. i don't understand why `2147483648` is `long` matters. – Jason Hu Sep 23 '14 at 20:19
  • 2
    @ouah:`Because 2147483648 is a long value as it does not fit an int` But the number is `-2147483648` and it is part of the range for int. – Cratylus Sep 23 '14 at 20:20
  • 1
    @Cratylus `-2147483648` is not an integer constant. `2147483648` is. `-2147483648` is the integer constant `2147483648` with the unary `-` operation. – ouah Sep 23 '14 at 20:21
  • i am curious about the practice. could somebody try with compilers and let us know the result of assigning `-2147483648` directly? – Jason Hu Sep 23 '14 at 20:25
  • @ouah What about this: http://codepad.org/bnb4UeLS – kotlomoy Sep 23 '14 at 20:30
  • @HuStmpHrrr let's take a system where `2147483648` is of type `long`. Then `int foo = -2147483648;` is the same as `int foo = (long) -2147483648;` which is the same actually as `int foo = INT_MIN;` as `-2147483648` is representable in a 32-bit `int`. – ouah Sep 23 '14 at 20:30
  • @ouah updated with a type-exposing sample (I know, its a C question, but that language doesn't have such a nicety as to expose type info in such a clean manner, and they both share similar `INT_MIN` logic). Hope that's ok. – WhozCraig Sep 23 '14 at 20:32
  • @WhozCraig sorry I added my own example as yours is C++ but the question is tagged C, feel free to add another answer with your example. – ouah Sep 23 '14 at 20:36
  • @ouah no no, yours drives it home nicely. Didn't think of utilizing sizeof. was more interested in exposing the actual *type*, and C++ deduction in concert with gcc's `__PRETTY_FUNCTION__` was a handy way to do it. This works. No need for a different answer (and it would be redundant if I did, as yours is clearly the right answer; +1 in case it wasn't blatantly apparent). – WhozCraig Sep 23 '14 at 20:38
  • @WhozCraig well I put it back as a second edit :) – ouah Sep 23 '14 at 20:41
  • @ouah i don't think compiler will do everything you said separately. – Jason Hu Sep 23 '14 at 20:42
  • @HuStmpHrrr it certainly won't, it was an example. – ouah Sep 23 '14 at 20:43
  • @ouah "You will most likely end up with: 4 8" - http://codepad.org/9TVJMzIu – kotlomoy Sep 23 '14 at 20:44
  • @kotlomoy compile it in c99 or c11 mode, by default with `gcc` you have c89 with extensions and the rules for integer constants are different in c89. – ouah Sep 23 '14 at 20:51
  • @ouah OK, your example works in C99: http://ideone.com/wpzCPC. What about adding information about difference between C89 and С99 to your answer? – kotlomoy Sep 23 '14 at 21:04
  • Actually, the data type of the integer literal `2147483648`, and by extension `-2147483648`, is `unsigned int` in ISO C90! This is the same as C89. – Galaxy Jul 07 '18 at 06:19