kadina
kadina

Reputation: 5376

char data type is not giving negative numbers by adding a positive number to the character which is holding maximum positive value

I am trying to add '1' to a character which is holding maximum positive value it can hold. It is giving 0 as output instead of giving -256.

#include <stdio.h>

int main() {
    signed char c = 255;
    printf("%d\n", c + 1 );
}

O / P : 0
c + 2 = 1;
c + 3 = 2;

As per my understanding, it should give negative numbers once it reaches the maximum limit (). Is this correct? I am testing on Ubuntu.

Upvotes: 0

Views: 562

Answers (2)

Lundin
Lundin

Reputation: 213678

There's several implicit conversions to keep track of here:

  • signed char c = 255; Is a conversion of the constant 255 which has type int, into a smaller signed char. This is "lvalue conversion through assignment" (initialization follows the rules of assignment) where the right operand gets converted to the type of the left.

    The actual conversion from a large signed type to a small signed type follows this rule:

    Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

    In practice, the very likely conversion to happen on a two's complement computer is that you end up with the signed char having the decimal value equivalent to 0xFF, which is -1.

  • c + 1 is an operation with two operands of types signed char and int respectively. For the + operator, it means that the usual arithmetic conversions are performed, see Implicit type promotion rules.

    Meaning c gets converted to int and the operation is carried out on int type, which is also the type of the result.

  • printf("%d\n", stuff ); The functions like printf accepting a variable number of arguments undergo an oddball conversion rule called the default argument promotions. In case of integers, it means that the integer promotions (see link above) are carried out. If you pass c + 1 as parameter, then the type is int and no promotion takes place. But if you had just passed c, then it gets implicitly promoted to int as per these rules. Which is why using %d together with character type actually works, even though it's the wrong conversion specifier for printing characters.


As per my understanding, it should give negative numbers once it reaches the maximum limit (). Is this correct?

If you simply do signed char c = 127; c++; then that's a signed overflow, undefined behavior with no predictable outcome.

If you do signed char c = 127; ... c + 1 then there's no overflow because of the implicit promotion to int.

If you do unsigned char c = 255; c++; then there is a well-defined wrap around since this is an unsigned type. c will become zero. Signed types do not have such a well-defined wrap around - they overflow instead.

In practice, signed number overflow is artificial nonsense invented by the C standard. All well-known computers just set an overflow and/or carry bit when you do overflow on assembler level, properly documented and well-defined by the core manual. The reason it turns "undefined behavior" in C is mainly because C allows for nonsensical signedness formats like one's complement or signed magnitude, that may have padding bits, trap representations or other such exotic, mostly fictional stuff.

Though nowadays, optimizing compilers take advantage of overflow not being allowed to happen, in order to generate more efficient code. Which is unfortunate, since we could have had both fast and 100% deterministic code if 2's complement was the only allowed format.

Upvotes: 1

chux
chux

Reputation: 153358

A signed char is very often 8-bit encoding values [-128...127].

signed char c = 255; is attempting to initialize c to a value outside the signed char range.

It is implementation behavior what happens next. Very commonly 255 is converted "mod" 256 to the value of -1.

signed char c = 255;
printf("%d\n", c     );  // -1 expected
printf("%d\n", c + 1 );  //  0 expected

As per my understanding, it should give negative numbers once it reaches the maximum limit (). Is this correct?

No. Adding 1 to the maximum int value is undefined behavior. There is no should. It might result in a negative number, might not, might exit code - it is not defined.

Had code been

signed char c = 127;
printf("%d\n", c + 1 );

c + 1 would be 128 and "128\n" would be printed as c + 1 is an int operation with an in range int sum.

Upvotes: 1

Related Questions