1
#include <stdio.h>
int main()
{
    char a = 0, b = 0, total = 0;

    a = 120;
    b = 9;

    total = a + b;

    printf("The sum of two numbers are: %d\n", a + b); // 129
    printf("The sum of two numbers are: %d\n", total); // -127

    return 0;
}

The value of 129 is incorrect. I know it has to do with the printf function but don't know why/how. The value of -127 is correct because of an overflow in total.

Russell
  • 87
  • 3
  • 2
    I'm guessing developing a familiarity with C's rules for [usual arithmetic conversions](https://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions) would help you understand the problem. – ShadowRanger Nov 23 '21 at 00:15
  • 1
    Does this answer your question? [Why (char) + (char) = (int) in C?](https://stackoverflow.com/questions/63207803/why-char-char-int-in-c) (Hmm, on second thought, that has other issues that add undefined behavior to the mix). There's a more broad explanation of this stuff under [Implicit type promotion rules](https://stackoverflow.com/q/46073295/364696). – ShadowRanger Nov 23 '21 at 00:16
  • 1
    *"The value of -127 is correct because of an overflow in total."* - integer overflow is *undefined behavior*, so not really good even if it seems correct. – Marco Bonelli Nov 23 '21 at 00:20
  • char is a data type containing 8 bits just like int having 32 bits. I believe my issue is the printf function. I debugged the program and the content of total was correct. I could test it with int but I chose char because of the fewer number of bits. I have to convert the values to binary and show the overflow using binary numbers for my students, trying to use smallest data type for the overflow demo. – Russell Nov 23 '21 at 00:24
  • @Russell there's no issue with the `printf`, just completely normal integer promotion. And `char` isn't necessary an 8-bit type. It's required to have at least 8 bits and `int` has at least 16 bits – phuclv Nov 23 '21 at 01:05

2 Answers2

4

The value of 129 is incorrect. I know it has to do with the printf function but don't know why/how.

No, it is not incorrect, and it has nothing to do with printf.

In printf("The sum of two numbers are: %d\n", a + b);, the operands of + are subject to the usual arithmetic conversions defined in C 2018 6.3.1.8. These conversions include the integer promotions, which convert char operands to int operands in normal C implementations.

Thus, in a + b, a is converted to int, b is converted to int, and their values are added to produce an int result. That result is 129, which is printed.

The value of -127 is correct because of an overflow in total.

When overflow occurs, the C standard does not define the behavior, so any result would be “correct” in that it is within what the C standard allows. Also, no result (from the program terminating) or any other behavior (such as corrupting other parts of the program) would be “correct” in the same sense.

However, no overflow occurs here. As with the printf, in total = a + b;, a and b are converted to int and then added, and the result is again 129. Then 129 is assigned to total. Since total is a char, and the maximum char value in your C implementation is 127, the conversion changes the value. C 2018 6.3.1.3 3 says either the result is implementation-defined or a signal is raised. Your C implementation apparently wraps the result modulo 256, so 129 becomes 129−256 = −127. (For example, GCC documents that this is what it does.)

Then printf("The sum of two numbers are: %d\n", total); passes −127 to printf, which of course prints “-127”.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

In firt case a and b are converted to int and then added. The result 129 fits the int

The second case the result of the addition does not fit into the char. It is I believe Implementation defined behaviour. In this case 129 in two's complement 8 bits format is -127.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • It's extra implementation defined, because the signedness of `char` is implementation defined; GCC (at least) even lets you change whether it's signed or unsigned with a command line switch (and the `char` type itself is technically distinct from `signed char` and `unsigned char`; basically, never do math with `char` that will cause it to fall outside the range 0 to 127 inclusive). – ShadowRanger Nov 23 '21 at 00:24
  • @ShadowRanger you try to generalize, but you do it wrong. char is from `CHAR_MIN` and `CHAR_MAX`. `char` does not have to be 8bits. Thre is even a special `#define` for that `CHAR_BIT`. – 0___________ Nov 23 '21 at 00:33
  • 1
    Ah, yes. I've worked on such a machine once (every type was 64 bits, `char` included). I suppose the more general rule is "Don't do math with plain `char` at all". That's why we have defined width integers. That said, C does require `CHAR_BIT >= 8`, so trusting that 0-127 are usable is safe nowadays (I think). Old pre-standard C systems did have seven bit `char` IIRC, but I sincerely hope I never run into such a system. – ShadowRanger Nov 23 '21 at 00:35
  • @Neil fixed size integers are not something we discuss here. – 0___________ Nov 23 '21 at 02:15