-1

Is the behavior described below predictable?

I've edited the numbers to be the limit of 2147483648. It still seems to work. Is that predictable?

a.out execution

e1r4p22% ./a.out
-2147483648
4

main.c

#include <stdio.h>
int main()
{
    int i = 2147483648;
    i = -i;
    printf("%d\n", i);
    printf("%lu\n", sizeof(int));
    return 0;
}
conradkleinespel
  • 6,560
  • 10
  • 51
  • 87
  • I assume you mean "predictable" as in "tellable from code," in which case the answer is: yes, it is. See http://stackoverflow.com/questions/1855459/maximum-value-of-int. – Andrew Cheong Jul 19 '13 at 21:32
  • The number is well away from the max 4-byt int limit of 2147483647, so it should negate without any "odd" effects. (In fact, *any* positive value should negate OK.) So I don't see anything strange or unexpected. – Hot Licks Jul 19 '13 at 21:35
  • 1
    Of course, try it with 2147483648 and you will see something different. – Hot Licks Jul 19 '13 at 21:37
  • 1
    `printf("%lu\n", sizeof(int));` has undefined behavior on systems where `size_t` is not `unsigned long`. Either use the correct format for `size_t`, namely `"%zu"`, or cast the value: `printf("%lu\n", (unsigned long)sizeof(int));` – Keith Thompson Jul 19 '13 at 21:43
  • changing the question in a way that invalidates all answers is lame - you should have asked a new question – user4815162342 Jul 20 '13 at 06:50

2 Answers2

1

You've changed your question, which invalidates the previous answers.

The behavior of your program is not predictable in general.

The C standard only guarantees that int can represent values in the range -32767 to +32767 (16 bits). On such a system, the constant 2147483648 is of type long or long long.

Even if int is 32 bits, no padding bits, and two's-complement, 2147483648 is outside the range of int, and may be of type long or long long.

This:

int i = 2147483648;

implicitly converts the long or long long value to int. The result is implementation-defined -- or it can raise an implementation-defined signal.

On many systems, the implementation-defined result is going to be -2147483648. IF it is, then this:

i = -i;

attempts to negate that value, yielding a result that's outside the range of int. Unlike a conversion, an overflowing arithmetic operator such as unary - has undefined behavior for signed types.

It's very likely that the program will behave as it does on your system, but no, it's not predictable as far as the C standard is concerned. The compiler is free to assume that your program's behavior is well defined, and generate code based on that assumption, so it's actually plausible that it could behave in some unexpected manner.

Also:

printf("%lu\n", sizeof(int));

This will work correctly if size_t (the result of the sizeof operator) is unsigned long on your system. If it isn't, then again, you have undefined behavior. The correct format for size_t is "%zu":

printf("%zu\n", sizeof(int));

That was introduced in C99, so some implementations (particularly Microsoft's) may not support it. You can also convert the argument to the appropriate type with a cast:

printf("%lu\n", (unsigned long)sizeof(int));

Whatever this code is trying to accomplish, there's almost certainly a clearer way to do it. If you want to be able to manipulate integers with values of 2147483648, long long or int64_t is guaranteed to be big enough.

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

The limit of an int is 2 147 483 647, according to limits.h and with sizeof(int) = 4. So yes, it's predictable, since 2 147 483 148 < 2 147 483 647.

nouney
  • 4,363
  • 19
  • 31
  • 3
    According to `limits.h` *on your system*. The C standard only guarantees that `INT_MAX >= 32767`. – Keith Thompson Jul 19 '13 at 21:42
  • @KeithThompson Look at the question. – nouney Jul 19 '13 at 21:45
  • 1
    Ok, on your system and the OP's system. *If* `sizeof (int) == 4` *and* `int` has no padding bits then `INT_MAX == 2147483647` (or more if `CHAR_BIT > 8`). But the question doesn't presume that `int` is 4 bytes, and the program's behavior is not predictable for all implementations. – Keith Thompson Jul 19 '13 at 21:49
  • The question presume that `int` is 4 bytes, look the output of `printf("%lu\n", sizeof(int));`, so I guess the OP doesn't care about other system. That becomes ridiculous. – nouney Jul 19 '13 at 21:57
  • 2
    The question doesn't *presume* that `int` is 4 bytes. That's part of the program's output, and the OP is asking whether the output is predictable. – Keith Thompson Jul 19 '13 at 21:59
  • 1
    Read the question. I see no such presumption. – Keith Thompson Jul 19 '13 at 22:03
  • @nouney he code should not just assume something that isn't guaranteed by standard. One of the problems we (industry) had (have?) is assuming that `sizeof(void *) == 4` or that `volatile` means atomic, both statements were true on majority of systems used at a time. – Maciej Piechotka Jul 19 '13 at 22:04