Reputation: 5376
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
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
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