#include<stdio.h>
int main()
{
char c =118,a=117;
c=c+10;
a=a+10;
printf("c:%d, a:%d\n", c,a);
}
The answer is c:-128, a:127.
Can someone explain me why c+10 is -128 and a+10 is 127?
Thanks in advance.
117 + 10 = 127 which is in range of the char type (-128 to 127)
If you open the calculator of your windows in programmer mode, you can see that 118 is represented as 1110110 in binary. also, 10 is represented as 1010. if we add this two, the result is 10000000. it is not in the range of the char type, and this number is equivalent to -128. so the -128 is printed.
because char is 8-bit signed in your compiler. So 118+10 is out of range (max is 127).
The implementation of your compiler "wraps" it around and you get -128 instead.
Signed 8-bit values range from -128 to 127. The bits for 127 are 0111 1111, and the bits for 128 would be 1000 0000. The problem is, in a signed number, the high order (leftmost) bit is the sign flag (0 is +, 1 is -). So, because it is signed, the computer interprets this as a negative number with the result -128 (This is called signed overflow, if I remember correctly, and everyone runs into this when programming at one point or another) (check out 2's complement to see why the low 7 bits are 128, not 0). You can get around this "problem" by declaring c and a as unsigned char instead of char.
BTW, you could save a variable this way:
char a=117;
printf("c:%d, a:%d\n", a+11,a+10);
In your case, a char is being represented by the compiler on your particular platform as a signed 8-bit value, and is in 2's complement reoresentation. That means the highest bit is the sign bit (if it's a 1, then the number is negative). So the range in binary for non-negative values is (in binary) 00000000-01111111 which is 0-127 in decimal. The negative values range (in binary) from 10000000 to 11111111 which is -128 to -1 in decimal.
If you start with 118, in binary that's:
01110110
If I add decimal 10, that's adding 1010 in binary:
01110110
+00001010
---------
10000000
You can see now the highest bit is set, meaning the number overflowed (became greater than the maximum 127 in decimal) and now represents a negative number. The 8-bit binary value 10000000 happens to represent -128 in decimal.
So adding (in decimal) 10 to the char value 118, yields -128.
Your value of a is 117, so 10+117 = 127 still fits in the 7 bits for a positive value of 127. You can do the above binary analysis as an exercise to see how that works.
Related
#include <stdio.h>
int main() {
char c = 125;
c = c + 10;
printf("%d", c);
return 0;
}
The output of this code is -121.
How this output is -121? Can you please explain?
If I add 100 instead of 10 with c then output is -31.
Why?
In C language the char type is an integer type able to represent all the characters required by the language itself. The standard does not specify whether it is a signed or unsigned type. After seeing the output, I can guess that your system uses a signed char of size 8 bits (7 value bits and one sign bit) and represent negative values in 2-complement.
So (as int) 125 + 10 = 135. 135 > 128 so the actual value is 135 - 256 = -121.
(In two complement mode, number are just wrapped over 2**SIZE_IN_BITS...)
How it works is that the type char in your compiler is a signed type which is 8 bits wide, and represents integer values using a system called two's complement.
In this system, the positive values go from 0 to 127 in binary like this:
00000000 0
00000001 1
00000010 2
00000011 3
... .
01111111 - 127
Upon the next increment, the highest bit flips to 1: we get 10000000. Then the subsequent binary values are interpreted as negative under two's complement:
10000000 128 -128
10000001 129 -127
10000010 130 -126
...
11111111 255 -1
The middle column, continuing to count up from 128, shows the unsigned interpretation of the 8 bit datum; it just keeps counting toward 255. That would be the behavior of the type unsigned char.
The right column, showing negative numbers, is the two's complement interpretation of exactly the same bit patterns. This instead covers a negative range of integers from -128 to -1.
Now what happens in C when we do c + 10?
Firstly, according to the rules of the C language, the c value of type char gets promoted to the type int, which has a much larger range. Thus the int value 125 is being added to the int value 10, resulting in the int value 135.
What happens next is that c is assigned that value, exactly as if by c = 135. But 135 it not in range; char only goes up to 127. Implementation-defined behavior ensues. The 135 value is somehow forced to fit, by discarding bits.
C compilers for two's complement machines (i.e. virtually all compilers on the planet) truncate wider integer value to narrower values simply by truncation of the bottom bits of the value to fit the smaller type.
So, the binary representation of 135 is this.
10000111
More precisely, suppose int is 32 bits wide. Then the representation of the int value 135 is:
00000000000000000000000010000111
This is converted to char by chopping off the top 24 bits, leaving the bottom 8:
------------------------10000111
So we end up with
10000111
in the char type. But what is that? Referring to our original table, we can add a few more rows:
10000000 128 -128
10000001 129 -127
10000010 130 -126
10000011 131 -125
10000100 132 -124
10000101 133 -123
10000110 134 -122
10000111 135 -121 <----
...
11111111 255 -1
And there is the -121.
char type is represented in memory as a byte (most of the time 8 bits), so it can represent values from -128 to +127. If you try to store a bigger value in the memory, it causes an overflow and the result is not what expected.
Here is a nice video explaning what overflow is.
The char is one byte that is 8 bit. one bit is for sign and 7 bits are all of you can use.
"char" range is:
char ==> -128 ~ 127
static_cast<char>(c+1) = 126
static_cast<char>(c+2) = 127
static_cast<char>(c+3) = -128
if you use from "unsigned char", positive range is increase.
unsigned char ==> 0 ~ 255
static_cast<unsigned char>(c+3) = 128
In memory 128 will be stored as 10000000. Where should I place the sign bit here since whole 1 byte is occupied by number 128 if i store -128 in byte datatype?
Can you please explain me?
Signed integers are typically represented in two's complement. This means that for a given positive number, the corresponding negative number is obtained by inverting all bits then adding 1.
A negative number in two's complement will have the high order bit set. This bit becomes the sign bit.
So for a number occupying a single byte, 11111111 represents -1, 11111110 represents -2, and so forth, all the way to 10000000 which represents -128. On the high end, 01111111 represents 127.
This means that a 1 byte signed integer cannot store the value 128. If you had a 1 byte unsigned integer then 10000000 would be 128 but then it could not hold any negative numbers.
A single byte means 8 bits, which mean you can choose from 2^8 = 256 values. In C representation for signed char (or signed integer of 1 byte) teh values chosen were from [-128, 127] including both extremes
you could cast to unsigned char, like
char s128 = (char)128;
if((unsigned char)s128==128){
printf("true\n");
}
What does signed mean in C? I have this table to show:
This says signed char 128 to +127. 128 is also a positive integer, so how can this be something like +128 to +127? Or do 128 and +127 have different meanings? I am referring to the book Apress Beginning C.
A signed integer can represent negative numbers; unsigned cannot.
Signed integers have undefined behavior if they overflow, while unsigned integers wrap around using modulo.
Note that that table is incorrect. First off, it's missing the - signs (such as -128 to +127). Second, the standard does not guarantee that those types must fall within those ranges.
By default, numerical values in C are signed, which means they can be both negative and positive. Unsigned values on the other hand, don't allow negative numbers.
Because it's all just about memory, in the end all the numerical values are stored in binary. A 32 bit unsigned integer can contain values from all binary 0s to all binary 1s. When it comes to 32 bit signed integer, it means one of its bits (most significant) is a flag, which marks the value to be positive or negative. So, it's the interpretation issue, which tells that value is signed.
Positive signed values are stored the same way as unsigned values, but negative numbers are stored using two's complement method.
If you want to write negative value in binary, first write positive number, next invert all the bits and last add 1. When a negative value in two's complement is added to a positive number of the same magnitude, the result will be 0.
In the example below lets deal with 8-bit numbers, because it'll be simple to inspect:
positive 95: 01011111
negative 95: 10100000 + 1 = 10100001 [positive 161]
0: 01011111 + 10100001 = 100000000
^
|_______ as we're dealing with 8bit numbers,
the 8 bits which means results in 0
The table is missing the minuses. The range of signed char is -128 to +127; likewise for the other types on the table.
It was a typo in the book; signed char goes from -128 to 127.
Signed integers are stored using the two's complement representation, in which the first bit is used to indicate the sign.
In C, chars are just 8 bit integers. This means that they can go from -(2^7) to 2^7 - 1. That's because we use the 7 last bits for the number and the first bit for the sign. 0 means positive and 1 means negative (in two's complement representation).
The biggest positive 7 bit number is (01111111)b = 2^7 - 1 = 127.
The smallest negative 7 bit number is (11111111)b = -128
(because 11111111 is the two's complement of 10000000 = 2^7 = 128).
Unsigned chars don't have signs so they can use all the 8 bits. Going from (00000000)b = 0 to (11111111)b = 255.
Signed numbers are those that have either + or - appended with them.
E.g +2 and -6 are signed numbers.
Signed Numbers can store both positive and negative numbers thats why they have bigger range.
i.e -32768 to 32767
Unsigned numbers are simply numbers with no sign with them. they are always positive. and their range is from 0 to 65535.
Hope it helps
Signed usually means the number has a + or - symbol in front of it. This means that unsigned int, unsigned shorts, etc cannot be negative.
Nobody mentioned this, but range of int in table is wrong:
it is
-2^(31) to 2^(31)-1
i.e.,
-2,147,483,648 to 2,147,483,647
A signed integer can have both negative and positive values. While a unsigned integer can only have positive values.
For signed integers using two's complement , which is most commonly used, the range is (depending on the bit width of the integer):
char s -> range -128-127
Where a unsigned char have the range:
unsigned char s -> range 0-255
First, your table is wrong... negative numbers are missing. Refering to the type char.... you can represent at all 256 possibilities as char has one byte means 2^8. So now you have two alternatives to set ur range. either from -128 to +128 or 0 to 255. The first one is a signed char the second a unsigned char. If you using integers be aware what kind of operation system u are using. 16 bit ,32 bit or 64 bit. Int (16 bit,32 bit,64 bit). char has always just 8 bit value.
It means that there will likely be a sign ( a symbol) in front of your value (+12345 || -12345 )
Here is my code
#include<stdio.h>
void main()
{
char ch = 129;
printf("%d", ch);
}
I get the output as -127. What does it mean?
It means that char is an 8-bit variable that can only hold 2^8 = 256 values, since the declaration is char ch, ch is a signed variable, which means it can store 127 negative and positive values. when you ask to go over 127 then the value starts over from -128.
Think of it like some arcade games where you go from one side of the screen to the other:
ch = 50;
-----> 50 is stored
|___________________________________|___________| since it fits
-128 0 50 127 between -127
and 128
ch = 129;
--- 129 goes over
--> 127 by 2, so
|__|____________________________________________| it 'lands' in
-128 -127 0 127 -127
BUT!! you shouldn't rely on this since it's undefined behaviour!
In honor of Luchian Grigore here's the bit representation of what's happening:
A char is a variable that will hold 8-bits or a byte. So we have 8 0's and 1's struggling to represent whatever value you desire. If the char is a signed variable it will represent whether it's a positive or negative number. You probably read about the one bit representing the sign, that's an abstraction of the true process; in fact it is only one of the first solutions implemented in electronics. But such a trivial method had a problem, you would have 2 ways of representing 0 (+0 and -0):
0 0000000 -> +0 1 0000000 -> -0
^ ^
|_ sign bit 0: positive |_ sign bit 1: negative
Inconsistencies guaranteed!! So, some very smart folks came up with a system called Ones' Complement which would represent a negative number as the negation (NOT operation) of its positive counterpart:
01010101 -> +85
10101010 -> -85
This system... had the same problem. 0 could be represented as 00000000 (+0) and 11111111 (-0). Then came some smarter folks who created Two's Complement, which would hold the negation part of the earlier method and then add 1, therefore removing that pesky -0 and giving us a shiny new number to our range: -128!. So how does our range look now?
00000000 +0
00000001 +1
00000010 +2
...
01111110 +126
01111111 +127
10000000 -128
10000001 -127
10000010 -126
...
11111110 -2
11111111 -1
So, this should give an idea of what's happening when our little processor tries to add numbers to our variable:
0110010 50 01111111 127
+0000010 + 2 +00000010 + 2
------- -- -------- ---
0110100 52 10000001 -127
^ ^ ^
|_ 1 + 1 = 10 129 in bin _| |_ wait, what?!
Yep, if you review the range table above you can see that up to 127 (01111111) the binary was fine and dandy, nothing weird happening, but after the 8'th bit is set at -128 (10000000) the number interpreted no longer held to its binary magnitude but to the Two's Complement representation. This means, the binary representation, the bits in your variable, the 1's and 0's, the heart of our beloved char, does hold a 129... its there, look at it! But the evil processor reads that as measly -127 cause the variable HAD to be signed undermining all its positive potential for a smelly shift through the real number line in the Euclidean space of dimension one.
It means you ran into undefined behavior.
Any outcome is possible.
char ch=129; is UB because 129 is not a representable value for a char for you specific setup.
Your char is most likely an 8-bit signed integer that is stored using Two's complement. Such a variable can only represent numbers between -128 and 127. If you do "127+1" it wraps around to -128. So 129 is equivalent to -127.
This comes from the fact that a char is coded on one byte, so 8 bits of data.
In fact char has a value coded on 7 bits and have one bit for the sign, unsigned char have 8 bits of data for its value.
This means:
Taking abcdefgh as 8 bits respectively (a being the leftmost bit, and h the rightmost), the value is encoded with a for the sign and bcdefgh in binary format for the real value:
42(decimal) = 101010(binary)
stored as :
abcdefgh
00101010
When using this value from the memory :
a is 0 : the number is positive, bcdefgh = 0101010 : the value is 42
What happens when you put 129 :
129(decimal) = 10000001(binary)
stored as :
abcdefgh
10000001
When using this value from the memory :
a is 0 : the number is negative, we should substract one and invert all bits in the value, so (bcdefgh - 1) inverted = 1111111 : the value is 127
The number is -127
On your system: char 129 has the same bits as the 8 bit signed integer -127.
An unsigned integer goes from 0 to 255, and signed integer -128 to 127.
Related (C++):
You may also be interested in reading the nice top answer to What is an unsigned char?
As #jmquigley points out. This is strictly undefined behavior and you should not rely on it.
Allowing signed integer overflows in C/C++
The char type is a 8-bit signed integer. If you interpret the representation of unsigned byte 129 in the two's complement signed representation, you get -127.
The type char can be either signed or unsigned, it's up to the compiler. Most compilers have it as `signed.
In your case, the compiler silently converts the integer 129 to its signed variant, and puts it in an 8-bit field, which yields -127.
char is 8 bits, signed. It can only hold values -128 to 127. When you try and assign 129 to it you get the result you see because the bit that indicates signing is flipped. Another way to think of it is that the number "wraps" around.
Whether a plain char is signed or unsigned, is implementation-defined behavior. This is a quite stupid, obscure rule in the C language. int, long etc are guaranteed to be signed, but char could be signed or unsigned, it is up to the compiler implementation.
On your particular compiler, char is apparently signed. This means, assuming that your system uses two's complement, that it can hold values of -128 to 127.
You attempt to store the value 129 in such a variable. This leads to undefined behavior, because you get an integer overflow. Strictly speaking, anything can happen when you do this. The program could print "hello world" or start shooting innocent bystanders, and still conform to ISO C. In practice, most (all?) compilers will however implement this undefined behavior as "wrap around", as described in other answers.
To sum it up, your code relies on two different behaviors that aren't well defined by the standard. Understanding how the result of such unpredictable code ends up in a certain way has limited value. The important thing here is to recognize that the code is obscure, and learn how to write it in a way that isn't obscure.
The code could for example be rewritten as:
unsigned char ch = 129;
Or even better:
#include <stdint.h>
...
uint8_t ch = 129;
As a rule of thumb, make sure to follow these rules in MISRA-C:2004:
6.1 The plain char type shall be used only for the storage and use of character values.
6.2 signed and unsigned char type shall be used only for the storage and use of numeric values.
Why the range of signed character is -128 to 127 but not -127 to 128 ?
That is because of the way two's complement encoding works: 0 is treated as a "positive" number (signed bit off), so, therefore, the number of available positive values is reduced by one.
In ones' complement encoding (which is not very common nowadays, but in the olden days, it was), there were separate values for +0 and -0, and so the range for an 8-bit quantity is -127 to +127.
In 8-bit 2's complement encoding numbers -128 and +128 have the same representation: 10000000. So, the designer of the hardware is presented with an obvious dilemma: how to interpret bit-pattern 10000000. Formally, it will work either way. If they decide to interpret it as +128, the resultant range will be -127..+128. If they decide to interpret it as -128, the resultant range will be -128..+127.
In actual real-life 2's complement representation the latter approach is chosen because it satisfies the following nice convention: all bit-patterns with 1 in higher-order bit represent negative numbers.
It is worth noting though, that language specification does not require 2's-complement implementations to treat the 100...0 bit pattern as a valid value in any signed integer type. E.g. implementations are allowed to restrict 8-bit signed char to -127..+127 range and regard 10000000 as an invalid bit combination (trap representation).
I think an easy way to explain this for the common soul is :
A bit is a value 0 or 1, or 2 possibilities
A 2-bit holds two combinations or 0 and 1 for four possible values : 00, 01, 10, and 11.
A 3-bit holds three combinations for a total of eight possible values : 000 to 111.
Thus n-bits holds n combinations for a total of 2^n possible values. Therefore, an 8-bit value is 2^8 = 256 possible values.
For signed numbers, the most significant bit (the first one reading the value from left to right) is the sign bit; that leaves a possibility of 2^(n-1) possible values. For an 8-bit signed number, this is 2^7 = 128 possible values for each sign. But since the positive sign includes the zero (0 to 127 = 128 different values, and 128 + 128 = 2^8 = 256), the negative sign includes -1 to... -128 for 128 different values also. Where :
10000000 = -128
...
11111111 = -1
00000000 = 0
...
01111111 = 127
#include <limits.h>
#include <stdio.h>
...
printf("range of signed character is %i ... %i", CHAR_MIN, CHAR_MAX );
If you just consider twos complement as arithmetic modulo 256, then the cutoff between positive and negative is purely arbitrary. You could just as well have put it at 63/-192, 254/-1, 130/-125, or anywhere else. However, as a standard signed integer format, twos complement came by convention put put the cutoff at 127/-128. This cutoff has one big benefit: the high bit being set corresponds directly to the number being negative.
As for the C language, it leaves the format of signed numbers up to the implementation, but only offers 3 choices of implementation, all of which use a "sign bit": sign/magnitude, ones complement, and twos complement.
If you look at ranges of chars and ints there seems to be one extra number on the negative side. This is because a negative number is always stored as 2’s compliment of its binary. For example, let us see how -128 is stored. Firstly, binary of 128 is calculated (10000000), then its 1’s compliment is obtained (01111111). A 1’s compliment is obtained by changing all 0s to 1s and 1s to 0s. Finally, 2’s compliment of this number, i.e. 10000000, gets stored. A 2’s compliment is obtained by adding 1 to the 1’s compliment. Thus, for -128, 10000000 gets stored. This is an 8-bit number and it can be easily accommodated in a char. As against this, +128 cannot be stored in a char because its binary 010000000 (left-most 0 is for positive sign) is a 9-bit number. However +127 can be stored as its binary 01111111 turns out to be a 8-bit number.
Step 1:
If you take 2's complement of any number from 0 up to 127 the bit number 8 will always be 1. So lets reserve that info.
Step2 :
if you find the -127 by applying 2's complement into +127 you will find "1 0 0 0 0 0 0 1" and finally if you substract 1 from this number then the smallest 8 bit number -128 will be achieved as "1 0 0 0 0 0 0 0"
As a result if we combine the info that we reserved at step 1 and the result from step2, we come to the conclusion that, the most significiant bit or bit number 8 in char containers must always be 1 so called signed bit.