Why use "strlen30()" instead of "strlen()"? - c

I've read and wondered about the source code of sqlite
static int strlen30(const char *z){
const char *z2 = z;
while( *z2 ){ z2++; }
return 0x3fffffff & (int)(z2 - z);
}
Why use strlen30() instead of strlen() (in string.h)??

The commit message that went in with this change states:
[793aaebd8024896c] part of check-in [c872d55493] Never use strlen(). Use our own internal sqlite3Strlen30() which is guaranteed to never overflow an integer. Additional explicit casts to avoid nuisance warning messages. (CVS 6007) (user: drh branch: trunk)

(this is my answer from Why reimplement strlen as loop+subtraction? , but it was closed)
I can't tell you the reason why they had to re-implement it, and why they chose int instead if size_t as the return type. But about the function:
/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
*/
static int strlen30(const char *z){
const char *z2 = z;
while( *z2 ){ z2++; }
return 0x3fffffff & (int)(z2 - z);
}
Standard References
The standard says in (ISO/IEC 14882:2003(E)) 3.9.1 Fundamental Types, 4.:
Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer. 41)
...
41): This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer
type
That part of the standard does not define overflow-behaviour for signed integers. If we look at 5. Expressions, 5.:
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined, unless such an expression is a constant expression
(5.19), in which case the program is ill-formed. [Note: most existing implementations of C + + ignore integer
overflows. Treatment of division by zero, forming a remainder using a zero divisor, and all floating point
exceptions vary among machines, and is usually adjustable by a library function. ]
So far for overflow.
As for subtracting two pointers to array elements, 5.7 Additive operators, 6.:
When two pointers to elements of the same array object are subtracted, the result is the difference of the subscripts of the two array elements. The type of the result is an implementation-defined signed integral type; this type shall be the same type that is defined as ptrdiff_t in the cstddef header (18.1). [...]
Looking at 18.1:
The contents are the same as the Standard C library header stddef.h
So let's look at the C standard (I only have a copy of C99, though), 7.17 Common Definitions :
The types used for size_t and ptrdiff_t should not have an integer conversion rank
greater than that of signed long int unless the implementation supports objects
large enough to make this necessary.
No further guarantee made about ptrdiff_t. Then, Annex E (still in ISO/IEC 9899:TC2) gives the minimum magnitude for signed long int, but not a maximum:
#define LONG_MAX +2147483647
Now what are the maxima for int, the return type for sqlite - strlen30()? Let's skip the C++ quotation that forwards us to the C-standard once again, and we'll see in C99, Annex E, the minimum maximum for int:
#define INT_MAX +32767
Summary
Usually, ptrdiff_t is not bigger than signed long, which is not smaller than 32bits.
int is just defined to be at least 16bits long.
Therefore, subtracting two pointers may give a result that does not fit into the int of your platform.
We remember from above that for signed types, a result that does not fit yields undefined behaviour.
strlen30 does applies a bitwise or upon the pointer-subtract-result:
| 32 bit |
ptr_diff |10111101111110011110111110011111| // could be even larger
& |00111111111111111111111111111111| // == 3FFFFFFF<sub>16</sub>
----------------------------------
= |00111101111110011110111110011111| // truncated
That prevents undefiend behaviour by truncation of the pointer-subtraction result to a maximum value of 3FFFFFFF16 = 107374182310.
I am not sure about why they chose exactly that value, because on most machines, only the most significant bit tells the signedness. It could have made sense versus the standard to choose the minimum INT_MAX, but 1073741823 is indeed slightly strange without knowing more details (though it of course perfectly does what the comment above their function says: truncate to 30bits and prevent overflow).

The CVS commit message says:
Never use strlen(). Use our own internal sqlite3Strlen30() which is guaranteed to never overflow an integer. Additional explicit casts to avoid nuisance warning messages. (CVS 6007)
I couldn't find any further reference to this commit or explanation how they got an overflow in that place. I believe that it was an error reported by some static code analysis tool.

Related

How does the Integer addition result arrive at its value in the case of overflow in C [duplicate]

Unsigned integer overflow is well defined by both the C and C++ standards. For example, the C99 standard (§6.2.5/9) states
A computation involving unsigned operands can never overflow,
because a result that cannot be represented by the resulting unsigned integer type is
reduced modulo the number that is one greater than the largest value that can be
represented by the resulting type.
However, both standards state that signed integer overflow is undefined behavior. Again, from the C99 standard (§3.4.3/1)
An example of undefined behavior is the behavior on integer overflow
Is there an historical or (even better!) a technical reason for this discrepancy?
The historical reason is that most C implementations (compilers) just used whatever overflow behaviour was easiest to implement with the integer representation it used. C implementations usually used the same representation used by the CPU - so the overflow behavior followed from the integer representation used by the CPU.
In practice, it is only the representations for signed values that may differ according to the implementation: one's complement, two's complement, sign-magnitude. For an unsigned type there is no reason for the standard to allow variation because there is only one obvious binary representation (the standard only allows binary representation).
Relevant quotes:
C99 6.2.6.1:3:
Values stored in unsigned bit-fields and objects of type unsigned char shall be represented using a pure binary notation.
C99 6.2.6.2:2:
If the sign bit is one, the value shall be modified in one of the following ways:
— the corresponding value with sign bit 0 is negated (sign and magnitude);
— the sign bit has the value −(2N) (two’s complement);
— the sign bit has the value −(2N − 1) (one’s complement).
Nowadays, all processors use two's complement representation, but signed arithmetic overflow remains undefined and compiler makers want it to remain undefined because they use this undefinedness to help with optimization. See for instance this blog post by Ian Lance Taylor or this complaint by Agner Fog, and the answers to his bug report.
Aside from Pascal's good answer (which I'm sure is the main motivation), it is also possible that some processors cause an exception on signed integer overflow, which of course would cause problems if the compiler had to "arrange for another behaviour" (e.g. use extra instructions to check for potential overflow and calculate differently in that case).
It is also worth noting that "undefined behaviour" doesn't mean "doesn't work". It means that the implementation is allowed to do whatever it likes in that situation. This includes doing "the right thing" as well as "calling the police" or "crashing". Most compilers, when possible, will choose "do the right thing", assuming that is relatively easy to define (in this case, it is). However, if you are having overflows in the calculations, it is important to understand what that actually results in, and that the compiler MAY do something other than what you expect (and that this may very depending on compiler version, optimisation settings, etc).
First of all, please note that C11 3.4.3, like all examples and foot notes, is not normative text and therefore not relevant to cite!
The relevant text that states that overflow of integers and floats is undefined behavior is this:
C11 6.5/5
If an exceptional condition occurs during the evaluation of an
expression (that is, if the result is not mathematically defined or
not in the range of representable values for its type), the behavior
is undefined.
A clarification regarding the behavior of unsigned integer types specifically can be found here:
C11 6.2.5/9
The range of nonnegative values of a signed integer type is a subrange
of the corresponding unsigned integer type, and the representation of
the same value in each type is the same. A computation involving
unsigned operands can never overflow, because a result that cannot be
represented by the resulting unsigned integer type is reduced modulo
the number that is one greater than the largest value that can be
represented by the resulting type.
This makes unsigned integer types a special case.
Also note that there is an exception if any type is converted to a signed type and the old value can no longer be represented. The behavior is then merely implementation-defined, although a signal may be raised.
C11 6.3.1.3
6.3.1.3 Signed and unsigned integers
When a value with integer
type is converted to another integer type other than _Bool, if the
value can be represented by the new type, it is unchanged.
Otherwise, if the new type is unsigned, the value is converted by
repeatedly adding or subtracting one more than the maximum value that
can be represented in the new type until the value is in the range of
the new type.
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 addition to the other issues mentioned, having unsigned math wrap makes the unsigned integer types behave as abstract algebraic groups (meaning that, among other things, for any pair of values X and Y, there will exist some other value Z such that X+Z will, if properly cast, equal Y and Y-Z will, if properly cast, equal X). If unsigned values were merely storage-location types and not intermediate-expression types (e.g. if there were no unsigned equivalent of the largest integer type, and arithmetic operations on unsigned types behaved as though they were first converted them to larger signed types, then there wouldn't be as much need for defined wrapping behavior, but it's difficult to do calculations in a type which doesn't have e.g. an additive inverse.
This helps in situations where wrap-around behavior is actually useful - for example with TCP sequence numbers or certain algorithms, such as hash calculation. It may also help in situations where it's necessary to detect overflow, since performing calculations and checking whether they overflowed is often easier than checking in advance whether they would overflow, especially if the calculations involve the largest available integer type.
Perhaps another reason for why unsigned arithmetic is defined is because unsigned numbers form integers modulo 2^n, where n is the width of the unsigned number. Unsigned numbers are simply integers represented using binary digits instead of decimal digits. Performing the standard operations in a modulus system is well understood.
The OP's quote refers to this fact, but also highlights the fact that there is only one, unambiguous, logical way to represent unsigned integers in binary. By contrast, Signed numbers are most often represented using two's complement but other choices are possible as described in the standard (section 6.2.6.2).
Two's complement representation allows certain operations to make more sense in binary format. E.g., incrementing negative numbers is the same that for positive numbers (expect under overflow conditions). Some operations at the machine level can be the same for signed and unsigned numbers. However, when interpreting the result of those operations, some cases don't make sense - positive and negative overflow. Furthermore, the overflow results differ depending on the underlying signed representation.
The most technical reason of all, is simply that trying to capture overflow in an unsigned integer requires more moving parts from you (exception handling) and the processor (exception throwing).
C and C++ won't make you pay for that unless you ask for it by using a signed integer. This isn't a hard-fast rule, as you'll see near the end, but just how they proceed for unsigned integers. In my opinion, this makes signed integers the odd-one out, not unsigned, but it's fine they offer this fundamental difference as the programmer can still perform well-defined signed operations with overflow. But to do so, you must cast for it.
Because:
unsigned integers have well defined overflow and underflow
casts from signed -> unsigned int are well defined, [uint's name]_MAX - 1 is conceptually added to negative values, to map them to the extended positive number range
casts from unsigned -> signed int are well defined, [uint's name]_MAX - 1 is conceptually deducted from positive values beyond the signed type's max, to map them to negative numbers)
You can always perform arithmetic operations with well-defined overflow and underflow behavior, where signed integers are your starting point, albeit in a round-about way, by casting to unsigned integer first then back once finished.
int32_t x = 10;
int32_t y = -50;
// writes -60 into z, this is well defined
int32_t z = int32_t(uint32_t(y) - uint32_t(x));
Casts between signed and unsigned integer types of the same width are free, if the CPU is using 2's compliment (nearly all do). If for some reason the platform you're targeting doesn't use 2's Compliment for signed integers, you will pay a small conversion price when casting between uint32 and int32.
But be wary when using bit widths smaller than int
usually if you are relying on unsigned overflow, you are using a smaller word width, 8bit or 16bit. These will promote to signed int at the drop of a hat (C has absolutely insane implicit integer conversion rules, this is one of C's biggest hidden gotcha's), consider:
unsigned char a = 0;
unsigned char b = 1;
printf("%i", a - b); // outputs -1, not 255 as you'd expect
To avoid this, you should always cast to the type you want when you are relying on that type's width, even in the middle of an operation where you think it's unnecessary. This will cast the temporary and get you the signedness AND truncate the value so you get what you expected. It's almost always free to cast, and in fact, your compiler might thank you for doing so as it can then optimize on your intentions more aggressively.
unsigned char a = 0;
unsigned char b = 1;
printf("%i", (unsigned char)(a - b)); // cast turns -1 to 255, outputs 255

Why is it more safe to place sizeof in malloc first?

What is the difference between
int *p = malloc( h * w * sizeof(*p) );
and
int *p = malloc( sizeof (*p) * h * w );
when h and w are of type int?
Why is it more safe to set sizeof(*p) at the first than at the last place in malloc?
I understood already that the latter form is used to insure size_t math and that the int operands would be widened to size_t before the calculation is done to prevent signed integer overflow as said here and here, but I don't quite understand how it exactly works.
When you write the sizeof operation first you usually insure that the calculation is done with at least size_t math. Let's determine what this means.
Problem with placing sizeof(X) at last:
Imagine the scenario, h has the value 200000 and w has the value 50000 (maybe got by accident).
Assuming that the maximum integer value an int can hold is 2147483647, which is common (The exact implementation-defined value you can read from the macro INT_MAX - header <limits.h>), Both are legit values an int can hold.
If you now use malloc( h * w * sizeof(*p) );, the part h * w is calculated first as the evaluation order of an arithmetic expression goes from left to right. With this, You would get a signed integer overflow as the result 10000000000 (10 billion) isn't possible to be represented by an int.
The behavior of a program in which integer overflow happens is undefined. The C standard states integer overflow even as example for undefined behavior at the specification of it:
3.4.3
1 undefined behavior
behavior, upon use of a non portable or erroneous program construct or of erroneous data, for which this document imposes no requirements
2 Note 1 to entry: Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
3 Note 2 to entry: J.2 gives an overview over properties of C programs that lead to undefined behavior.
4 EXAMPLE An example of undefined behavior is the behavior on integer overflow.
Source: C18, §3.4.3
Placing sizeof(X) at the first place instead:
If you use the sizeof operation first instead, like malloc( sizeof(*p) * h * w );, you usually don't have the risk to get an integer overflow.
This because of two reasons.
sizeof gains a value of the unsigned integer type size_t. size_t has on the most modern implementations a higher integer conversion rank and size than an int. Common values: sizeof(size_t) == 8 and sizeof(int) == 4.
This is important for point 2., something called integer promotion (arithmetic conversion) which occurs in arithmetic expressions.
In expression often happen automatic type conversions of operands. This is called integer or implicit type promotion. For more information about this you can take a look at this useful FAQ.
For this promotion, the conversion rank of an integer type is important since the type of the operand of the less integer conversion rank get promoted to the type of the operand of the higher integer conversion rank.
Looking at the exact phrases from the C standard:
"Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank."
Source: C18, §6.3.1.8/1
Also conversions of the signedness can happen here and that's what is important in this case as described later on.
"Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type."
....
"Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type."
Source: C18, §6.3.1.8/1
If size_t has higher or at least equal integer conversion rank than int and int isn't be able to represent all values of size_t (which is fulfilled since int usually has less size than size_t as said earlier), the operands h and w of type int get promoted to type size_t before the calculation.
Importance of the signedness conversion to an unsigned integer:
Now you might ask: Why is the signedness conversion to an unsigned integer important?
There are also two reasons here by which the second is more important but for the sake of completeness I want to cover both.
An unsigned integer has always a wider positive range than an signed integer of the the same integer conversion rank. This is because a signed integer also always need to represent a negative range of values. An unsigned integer has no negative range and can therefore represent almost twice more positive values than an signed integer.
But even more important:
An unsigned integer can never overflow!
"A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."
Source: C18, §6.2.5/9 (emphasize mine)
That's the reason why placing the sizeof operation first as in malloc( sizeof(*p) * h * w ); is more safe.
However, in the case you will get over the limit by using an unsigned integer, due to wrapping around the allocated memory would be too small to use it for the desired purpose. Accessing non-allocated memory would also invoke undefined behavior.
But nonetheless it gives you protection from getting undefined behavior at the call to malloc() itself.
Side notes:
Note that placing sizeof at the second position malloc( h * sizeof(*p) * w ) would technically achieve the same effect although it might decrease readability.
If the arithmetic expression in the call to malloc() only has one or 2 operands (e.g. sizeof(x) and an int) the order doesn't matter. But to stick to convention, I would recommend to use the same style by placing the sizeof() always first: malloc(sizeof(int) * 4). In this way you don't risk accidentally forgetting it by having 2 int operands.
Using an unsigned integer type like size_t for h and w can also be a smarter alternative. It insures that no undefined overflow will happen in the first place and beside that it's more appropriate as h and w aren't meant to have negative values.
Related:
How do I detect unsigned integer multiply overflow?
Why is unsigned integer overflow defined behavior but signed integer overflow isn't?
unsigned int vs. size_t
Why is it more safe to set sizeof(*p) at the first than at the last place in malloc?
The short answer is: It isn't (or at least shouldn't be) more safe.
Longer answer:
Any integer calculation may overflow - some with undefined behavior as result - some with incorrect results and (maybe) subsequent program failure.
Any integer calculation must consider whether overflow can happen. If you write a program that allocates more than 2G of memory in a single malloc call, I'm sure you are already aware of that and have ensured that both h and w have appropriate types.
Further, the standard doesn't tell exactly what the maximum values for integer types are. So if you want to program "safe" make sure to ask about those limits at run time.
To put in another way: "more safe" is not a programming goal. If you write programs that operate on the edge, you make them safe - not just "more safe"
While multiplication is commutative, apparently compilers do not scan ahead for the largest type, sizeof() being size_t, which on 64 bit computers is unsigned long (2^64 - 1), so the order is important for preventing overflow, which in many languages happens silently, even though all CPUs provide that information as a status bit if not as an interrupt! Of course, some programmers want a silent overflow to get the reside mod type size, but that's a sad reason to make the rest of us suffer!

difference of unsigned integer - standard supported way to get signed result?

assuming two arbitrary timestamps:
uint32_t timestamp1;
uint32_t timestamp2;
Is there a standard conform way to get a signed difference of the two beside the obvious variants of converting into bigger signed type and the rather verbose if-else.
Beforehand it is not known which one is larger, but its known that the difference is not greater than max 20bit, so it will fit into 32 bit signed.
int32_t difference = (int32_t)( (int64_t)timestamp1 - (int64_t)timestamp2 );
This variant has the disadvantage that using 64bit arithmetic may not be supported by hardware and is possible of course only if a larger type exists (what if the timestamp already is 64bit).
The other version
int32_t difference;
if (timestamp1 > timestamp2) {
difference = (int32_t)(timestamp1 - timestamp2);
} else {
difference = - ((int32_t)(timestamp2 - timestamp1));
}
is quite verbose and involves conditional jumps.
That is with
int32_t difference = (int32_t)(timestamp1 - timestamp2);
Is this guaranteed to work from standards perspective?
You can use a union type pun based on
typedef union
{
int32_t _signed;
uint32_t _unsigned;
} u;
Perform the calculation in unsigned arithmetic, assign the result to the _unsigned member, then read the _signed member of the union as the result:
u result {._unsigned = timestamp1 - timestamp2};
result._signed; // yields the result
This is portable to any platform that implements the fixed width types upon which we are relying (they don't need to). 2's complement is guaranteed for the signed member and, at the "machine" level, 2's complement signed arithmetic is indistinguishable from unsigned arithmetic. There's no conversion or memcpy-type overhead here: a good compiler will compile out what's essentially standardese syntactic sugar.
(Note that this is undefined behaviour in C++.)
Bathsheba's answer is correct but for completeness here are two more ways (which happen to work in C++ as well):
uint32_t u_diff = timestamp1 - timestamp2;
int32_t difference;
memcpy(&difference, &u_diff, sizeof difference);
and
uint32_t u_diff = timestamp1 - timestamp2;
int32_t difference = *(int32_t *)&u_diff;
The latter is not a strict aliasing violation because that rule explicitly allows punning between signed and unsigned versions of an integer type.
The suggestion:
int32_t difference = (int32_t)(timestamp1 - timestamp2);
will work on any actual machine that exists and offers the int32_t type, but technically is not guaranteed by the standard (the result is implementation-defined).
The conversion of an unsigned integer value to a signed integer is implementation defined. This is spelled out in section 6.3.1.3 of the C standard regarding integer conversions:
1 When a value with integer type is converted to another integer type other than
_Bool ,if the value can be represented by the new type, it is unchanged.
2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than
the maximum value that can be represented in the new type
until the value is in the range of the new type. 60)
3 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.
On implementations people are most likely to use, the conversion will occur the way you expect, i.e. the representation of the unsigned value will be reinterpreted as a signed value.
Specifically GCC does the following:
The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object
of that type (C90 6.2.1.2, C99 and C11 6.3.1.3).
For conversion to a type of width N, the value is reduced modulo 2^N
to be within range of the type; no signal is raised.
MSVC:
When a long integer is cast to a short, or a short is cast to a char,
the least-significant bytes are retained.
For example, this line
short x = (short)0x12345678L;
assigns the value 0x5678 to x, and this line
char y = (char)0x1234;
assigns the value 0x34 to y.
When signed variables are converted to unsigned and vice versa, the
bit patterns remain the same. For example, casting -2 (0xFE) to an
unsigned value yields 254 (also 0xFE).
So for these implementations, what you proposed will work.
Rebranding Ian Abbott's macro-packaging of Bathseba's answer as an answer:
#define UTOS32(a) ((union { uint32_t u; int32_t i; }){ .u = (a) }.i)
int32_t difference = UTOS32(timestamp1 - timestamp2);
Summarizing the discussions on why this is more portable than a simple typecast: The C standard (back to C99, at least) specifies the representation of int32_t (it must be two's complement), but not in all cases how it should be cast from uint32_t.
Finally, note that Ian's macro, Bathseba's answer, and M.M's answers all also work in the more general case where the counters are allowed to wrap around 0, as is the case, for example, with TCP sequence numbers.

C assigning values greater than data type ranges

In C int type can having following +ve range of values 2,147,483,647
source:https://msdn.microsoft.com/en-IN/library/s3f49ktz.aspx
I would like to know what happens if I assign values greater than int can hold, how the values are truncated or what is exactly stored, if I do this
int var=2147483648;
int var = 2147483648;
The actual behavior for signed integers is implementation-defined. Most possibly the value will be narrowed (in other words "cut-of") to four least significant bytes (assuming that sizeof(int) = 4).
The constant 2147483648 is likely of type long (or long long if former is not enough to hold it), so what is actually happening here is like:
int var = (int) 2147483648LL;
The actual value after conversion is -2147483648 as only sign bit is set (assuming two's complement representation).
Citing from C11 (N1570) §6.3.1.3/p3 Signed and unsigned integers (emphasis mine):
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.
For instance, with GCC, the result is to reduce result modulo 2^N, which is effectively the same as bytes "cut off":
For conversion to a type of width N, the value is reduced modulo 2^N
to be within range of the type; no signal is raised.
As you cited the linked statement, it is wrong. However, the linked page states correctly that it is valid for that specific implementation. Read the standard for minimum ranges of the standard types.
Actual sizes are in limits.h. You should not rely on anything else. If you need a specific size, use stdint.h types.
If you assign a signed value to an object which cannot hold that value, the result is implementation defined.
A proper compilers allows to enable warnings for such issues - use them!
OTOH, for an unsigned value, it is very well defined (same section of the standard). Simply put, the upper bits are just ignored.
Typically if the type is initialised in the source code, as in your example, you could get a compiler warning or error. Compile with highest warning levels possible.
If the overflow is the result of a calculation, it would be undefined. In practice this results in a wrap around or truncation, possibly with an overflow error.
In C, there is no checking for overflow. The result is implementation defined.

Cyclic Nature of char datatype [duplicate]

This question already has answers here:
Simple Character Interpretation In C
(9 answers)
Closed 5 years ago.
I had been learning C and came across topic called Cyclic Nature of Data Type in C.
It is like example
char c=125;
c=c+10;
printf("%d",c);
The output is -121.
the logic given was
125+1= 126
125+2= 127
125+3=-128
125+4=-127
125+5=-126
125+6=-125
125+7=-124
125+8=-123
125+9=-122
125+10=-121
This is due to cyclic nature if char datatype. Y does Char exhibit cyclic nature?? How is it possible to char??
On your system char is signed char. When a signed integral type overflows, the result is undefined. It may or may not be cyclic. Although on most of the machines performing 2's complement arithmetic, you may observe this as cyclic.
The char data type is signed type, as per your implementation. As such it can store values in range: -128 to 127. When you store a value greater than 127, you would end up with a value that might be in negative or positive number, depending on how large is the value stored and what kind of platform you are working on.
Signed integer overflow is undefined behavior in C and then not at all unsigned numbers are guaranteed to wrap around.
char isn’t special in this regard (besides its implementation-defined signedness), all conversions to signed types usually exhibit this “cyclic nature”. However, there are undefined and implementation-defined aspects of signed overflow, so be careful when doing such things.
What happens here:
In the expression
c=c+10
the operands of + are subject to the usual arithmetic conversions. They include integer promotion, which converts all values to int if all values of their type can be represented as an int. This means, the left operand of + (c) is converted to an int (an int can hold every char value1)). The result of the addition has type int. The assignment implicitly converts this value to a char, which happens to be signed on your platform. An (8-bit) signed char cannot hold the value 135 so it is converted in an implementation-defined way 2). For gcc:
For conversion to a type of width N, the value is reduced modulo 2N to be within range of the type; no signal is raised.
Your char has a width of 8, 28 is 256, and 135 ☰ -121 mod 256 (cf. e.g. 2’s complement on Wikipedia).
You didn’t say which compiler you use, but the behaviour should be the same for all compilers (there aren’t really any non-2’s-complement machines anymore and with 2’s complement, that’s the only reasonable signed conversion definition I can think of).
Note, that this implementation-defined behaviour only applies to conversions, not to overflows in arbitrary expressions, so e.g.
int n = INT_MAX;
n += 1;
is undefined behaviour and used for optimizations by some compilers (e.g. by optimizing such statements out), so such things should definitely be avoided.
A third case (unrelated here, but for sake of completeness) are unsigned integer types: No overflow occurs (there are exceptions, however, e.g. bit-shifting by more than the width of the type), the result is always reduced modulo 2N for a type with precision N.
Related:
A simple C program output is not as expected
Allowing signed integer overflows in C/C++
1 At least for 8-bit chars, signed chars, or ints with higher precision than char, so virtually always.
2 The C standard says (C99 and C11 (n1570) 6.3.1.3 p.3) “[…] either the result is implementation-defined or an implementation-defined signal is raised.” I don’t know of any implementation raising a signal in this case. But it’s probably better not to rely on that conversion without reading the compiler documentation.

Resources