There's several implicit conversions to keep track of here:
- signed char c = 255;Is a conversion of the constant- 255which 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 + 1is an operation with two operands of types- signed charand- intrespectively. For the + operator, it means that the usual arithmetic conversions are performed, see Implicit type promotion rules.
 - Meaning - cgets converted to- intand the operation is carried out on- inttype, which is also the type of the result.
 
- printf("%d\n", stuff );The functions like- printfaccepting 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 + 1as parameter, then the type is- intand no promotion takes place. But if you had just passed- c, then it gets implicitly promoted to- intas per these rules. Which is why using- %dtogether 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.