What does signed and unsigned values mean? - c

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 )

Related

How a single byte can hold -128 value

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");
}

Addition of char value in c

#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.

Tilde C unsigned vs signed integer

For example:
unsigned int i = ~0;
Result: Max number I can assign to i
and
signed int y = ~0;
Result: -1
Why do I get -1? Shouldn't I get the maximum number that I can assign to y?
Both 4294967295 (a.k.a. UINT_MAX) and -1 have the same binary representation of 0xFFFFFFFF or 32 bits all set to 1. This is because signed numbers are represented using two's complement. A negative number has its MSB (most significant bit) set to 1 and its value determined by flipping the rest of the bits, adding 1 and multiplying by -1. So if you have the MSB set to 1 and the rest of the bits also set to 1, you flip them (get 32 zeros), add 1 (get 1) and multiply by -1 to finally get -1.
This makes it easier for the CPU to do the math as it needs no special exceptions for negative numbers. For example, try adding 0xFFFFFFFF (-1) and 1. Since there is only room for 32 bits, this will overflow and the result will be 0 as expected.
See more at:
http://en.wikipedia.org/wiki/Two%27s_complement
unsigned int i = ~0;
Result: Max number I can assign to i
Usually, but not necessarily. The expression ~0 evaluates to an int with all (non-padding) bits set. The C standard allows three representations for signed integers,
two's complement, in which case ~0 = -1 and assigning that to an unsigned int results in (-1) + (UINT_MAX + 1) = UINT_MAX.
ones' complement, in which case ~0 is either a negative zero or a trap representation; if it's a negative zero, the assignment to an unsigned int results in 0.
sign-and-magnitude, in which case ~0 is INT_MIN == -INT_MAX, and assigning it to an unsigned int results in (UINT_MAX + 1) - INT_MAX, which is 1 in the unlikely case that unsigned int has a width (number of value bits for unsigned integer types, number of value bits + 1 [for the sign bit] for signed integer types) smaller than that of int and 2^(WIDTH - 1) + 1 in the common case that the width of unsigned int is the same as the width of int.
The initialisation
unsigned int i = ~0u;
will always result in i holding the value UINT_MAX.
signed int y = ~0;
Result: -1
As stated above, only if the representation of signed integers uses two's complement (which nowadays is by far the most common representation).
~0 is just an int with all bits set to 1. When interpreted as unsigned this will be equivalent to UINT_MAX. When interpreted as signed this will be -1.
Assuming 32 bit ints:
0 = 0x00000000 = 0 (signed) = 0 (unsigned)
~0 = 0xffffffff = -1 (signed) = UINT_MAX (unsigned)
Paul's answer is absolutely right. Instead of using ~0, you can use:
#include <limits.h>
signed int y = INT_MAX;
unsigned int x = UINT_MAX;
And now if you check values:
printf("x = %u\ny = %d\n", UINT_MAX, INT_MAX);
you can see max values on your system.
No, because ~ is the bitwise NOT operator, not the maximum value for type operator. ~0 corresponds to an int with all bits set to 1, which, interpreted as an unsigned gives you the max number representable by an unsigned, and interpreted as a signed int, gives you -1.
You must be on a two's complement machine.
Look up http://en.wikipedia.org/wiki/Two%27s_complement, and learn a little about Boolean algebra, and logic design. Also learning how to count in binary and addition and subtraction in binary will explain this further.
The C language used this form of numbers so to find the largest number you need to use 0x7FFFFFFF. (where you use 2 FF's for each byte used and the leftmost byte is a 7.) To understand this you need to look up hexadecimal numbers and how they work.
Now to explain the unsigned equivalent. In signed numbers the bottom half of numbers are negative (0 is assumed positive so negative numbers actually count 1 higher than positive numbers). Unsigned numbers are all positive. So in theory your highest number for a 32 bit int is 2^32 except that 0 is still counted as positive so it's actually 2^32-1, now for signed numbers half those numbers are negative. which means we divide the previous number 2^32 by 2, since 32 is an exponent we get 2^31 numbers on each side 0 being positive means the range of an signed 32 bit int is (-2^31, 2^31-1).
Now just comparing ranges:
unsigned 32 bit int: (0, 2^32-1)
signed 32 bit int: (-2^31, 2^32-1)
unsigned 16 bit int: (0, 2^16-1)
signed 16 bit int: (-2^15, 2^15-1)
you should be able to see the pattern here.
to explain the ~0 thing takes a bit more, this has to do with subtraction in binary. it's just adding 1 and flipping all the bits then adding the two numbers together. C does this for you behind the scenes and so do many processors (including the x86 and x64 lines of processors.)
Because of this it's best to store negative numbers as though they are counting down, and in two's complement the added 1 is also hidden. Because 0 is assumed positive thus negative numbers can't have a value for 0, so they automatically have -1 (positive 1 after the bit flip) added to them. when decoding negative numbers we have to account for this.

Range of signed char

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.

addition of "binary" numbers

What is the result of adding the binary numbers 01000001 and 11111111 on an 8 bit machine?
If we are supposed to interpret this with the rules of C (it is tagged as such), for the signed case there are three interpretations of these numbers possible, corresponding to the three sign representations that are allowed in C.
For the unsigned case the standard requires that unsigned arithmetic wraps silently. All computation is done modulo 256 in that case.
Integer overflow.
If the numbers are unsigned (i.e. modular), 0100000 (with modular 8-bit math, addition of 11111111 is equal to subtraction of 1).
If both values are unsigned, then the result is 320 in decimal. Both operands are promoted to int before the addition, and int is required by the standard to have at least 16 bits, even on an 8 bit machine. The question doesn't make any restrictions for the result.
Unless you want the "wrong result fast", the answer is 320.
Correctly adding two numbers (in whatever representation) anywhere (including 8-bit machines) results in a unique number that can be represented in a multitude of different ways.
320 can be represented as 320 (usual decimal (base-10) representation) or 101000000 (binary representation) or 253413120100 (factoradic), ...
I think you just add the numbers, then cut the overflowing bits (from the left)
if it's only 8 bit, the maximum you can have is 255 (1111 1111) if the value is unsigned and 127 if it is signed (-128 being the lowest). Therefore, doing this addition will cause overflow, which goes back to 0 and then keeps counting. Think of it as your car miles meter: if there can only be, say, 8 digits on the counter, and your counter is at 99 999 999 miles, if you add one more, the counter will go back to 0.
If these are signed integers, they represent 65 and -128 -1. Adding them will give -63 64.
If these are unsigned integers, they represent 65 and 255. Since the sum can not be represented in 8 bits, the result will be 64 and the overflow bit will be set.

Resources