Output of hexadecimal in C++ - c++

This is an example in "A Complete Guide to Programming in C++" (Ulla Kirch-Prinz & Peter Prinz)
Example:
cout << dec << -1 << " " << hex << -1;
This statement causes the following output on a 32-bit system:
-1 ffffffff
Could anyone please explain why the second output is ffffffff?
I have trouble with the explanation in the book that says:
When octal or hexadecimal numbers are output, the bits of the number
to be output are always interpreted as unsigned! In other words, the
output shows the bit pattern of a number in octal or hexadecimal
format.

That's because most modern machines use two's complement signed integer representation.
In two's complement, the highest bit is used as a sign bit. If it is set, the number is considered negative, and to get its absolute (positive) value you need to subtract it from 2N, i.e. take it's two's complement.
If you had an 8-bit number, 00000001, it's two's complement would be 100000000-00000001 = 11111111 (or 0xFF hex). So -1 is represented as all 1's in binary form.
It's a very convenient system because you can perform arithmetic as if the numbers were unsigned (letting them overflow), then simply interpret the result as signed, and it will be correct.

compiler implement negative numbers for signed variables in ths following way, if the highest bit is true, your number implements like (VALUE_RANGE - variable)
here is an example on 8 bit numbers, i hope you will expand it.
char 0 1 2 ... 10 ... 126 127 -128 -127 -126 ... -10 ... -2 -1
uchar 0 1 2 ... 10 ... 126 127 128 129 130 ... 246 ... 254 255
hex 0 1 2 ... A ... 7E 7F 80 81 82 ... F6 ... FE FF

The text you've highlighted is saying that the output is equivalent to
cout << dec << -1 << " " << hex << (unsigned)-1;
In a 2's complement system (which any desktop PC is these days), the bit pattern for -1 has all bits set to 1.
For a 32 bit int therefore, the output will be ffffffff.
Finally, note that if int (and therefore unsigned) are 32 bits, the type of the literal 0xffffffff is unsigned.
References:
http://en.cppreference.com/w/cpp/language/integer_literal
https://en.wikipedia.org/wiki/Two%27s_complement

Related

C++ Primer Exercise 4.25 converting binary number

I have a question regarding the exercise 4.25 in C++ Primer:
Exercise 4.25: What is the value of ~'q' << 6 on a machine with 32-bit
ints and 8 bit chars, that uses Latin-1 character set in which 'q' has the
bit pattern 01110001?
I have the solution in binary, but I don't understand how this converts to int:
int main()
{
cout << (std::bitset<8 * sizeof(~'q' << 6)>(~'q' << 6))<<endl;
cout << (~'q' << 6) << endl;
return 0;
}
After executing, the following 2 lines are printed:
11111111111111111110001110000000
-7296
The first line is what I expected, but I don't understand how is it converted to -7296.
I would expect a lot larger number. Also online converters give a different result from this.
Thanks in advance for the help.
In order to answer the question, we need to analyze what types are the partial expressions and what is the precedence of the operators in play.
For this we could refer to character constant and operator precedence.
'q' represents an int as described in the first link:
single-byte integer character constant, e.g. 'a' or '\n' or '\13'.
Such constant has type int ...
'q' thus is equivalent to the int value of its Latin-1 code (binary 01110001) but expanded to fit a 32-bit integer: 00000000 0000000 00000000 01110001.
The operator ~ precedes the operator << so the bitwise negation will be performed first. The results is 11111111 11111111 11111111 10001110.
Then a bitwise shift left is performed (dropping the left 6 bits of the value and padding with 0-s on the right): 11111111 11111111 11100011 10000000.
Now, regarding your second half of the question: cout << (~'q' << 6) << endl; interpretes this value as an int (signed). The standard states:
However, all C++ compilers use two's complement representation, and as of C++20, it is the only representation allowed by the standard, with the guaranteed range from āˆ’2Nāˆ’1 to +2Nāˆ’1āˆ’1
(e.g. -128 to 127 for a signed 8-bit type).
The two's complement value for 11111111 11111111 11100011 10000000 on a 32-bit machine results in the binary code for the decimal -7296.
The number is not large as you would expect, because when you start from -1 decimal (11111111 11111111 11111111 11111111 binary) and count down, the binary representations all have a lot of leading 1-s. The leftmost bit is 1 for a negative number and 0 for a positive number. When you expand the negative value to more bits (e.g. from 32 to 64), you would add more 1-s to the left until you reach 64 bits. More information can be found here. And here is an online converter.
I don't understand how is it converted to -7296.
It(the second value) is the Decimal from signed 2's complement
~'q' << 6
= (~'q') << 6
= (~113) << 6
= (~(0 0111 0001)) << 6
= 1 1000 1110 << 6
= -7296
You may have forgotten to add some 0's in front of 113.

How come 129, which is 8-bit number, is stored as -127 in signed char in c++

I declared signed char and stored 129, an 8-bit number, in it. when typecasted it into integer and printed the result, its -127. I understand that it is overflow, but the confusion occurs when you look at the binary of 129 which is 10000001. In signed char, most significant bit is reserved as a sign bit and rest of the 7 bits are used to store the number's binary. According to this concept, 129 should be stored as -1. MSG representing negative sign and rest of the 7-bits are 0000001 which makes 1.
How come 129 becomes -127 when the binary of 129 makes -1.
#include <iostream>
using namespace std;
int main() {
char a=129;
cout<<(int) a; // OUTPUT IS -127
return 0;
}
Your current idea of negative numbers is like this:
00000001 == 1
10000001 == -1
01111111 == 127
11111111 == -127
This means that you have only available range of integers -127...127 and
also you have two zeros. (00000000 == 0 and 10000000 == -0)
Best method is so called two's complement. For any number x, you negate binary representation and add 1 to get -x.
It means:
00000001 == 1
11111111 == -1
01111111 == 127
10000001 == -127
10000000 == -128
In this way only 00000000 is zero and you have the widest range -128...127.
Also CPU don't need additional instructions for adding signed numbers because it's identical to unsigned number addition and subtraction.
You may wonder, why to add 1. Without it, it's called one's complement.
https://en.wikipedia.org/wiki/Ones%27_complement
Every current computer stores low level signed integers in a format known as two's complement.
In two's complement, MAX_POSITIVE+1 is MIN_NEGATIVE.
0x00000000 is 0.
0x00....0V is V.
0x01....11 is MAX_POSITIVE
0x10....00 is MIN_NEGATIVE
0x11....11 is -1.
This looks weird at first glance.
But, it means that the logic of addition for positive and negative numbers is the same. In fact, signed and unsigned math works out to be the same, except on overflow a positive signed number becomes a negative number, while the overflow of a positive unsigned number wraps around to 0.
Note that in C++, overflowing a signed number is undefined behavior, not because the hardware traps it, but because by making it UB the compiler is free to assume "adding positive numbers together is positive". But at the machine code level, the implementation is 2s complement, and C++ has defined converting from signed to unsigned as following the 2s complement assumption.

Seven bit and two compliment

If we use seven-bit two's complement binary representation for integers, what is
The number of integers (things) that can be represented in this way?
The smallest (most) negative integer that can be represented in this way?
The largest positive integer that can be represented in this way?
This is a CS homework question that I am having trouble answering and explaining. Any help would be appreciated.
So its really easy
Counting in binary usually goes like
>00000000 (8) = 0
>00000001 (8) = 1
>00000010 (8) = 2
>00000011 (8) = 3
>etc...etc.
In 7 bit the last bit is what decides if its a negative or positive
1 being negative and 0 being positive
> 10000000 = -128
> 10000001 = -127
> 10000010 = -126
> On...and on...
> 11111111 = -1
> 00000000 = 0
> 00000001 = 1
> 01111111 = 127
So lowest you can go is -128
Highest you can go is 127
Approved answer is not correct.
With 7-bits of 2's complement, it could range from -64 to 63. (traditionally, 7 bits can only go up to 2^n-1 which is 128 but MSB is reserved for sign, so we could have 6 bits to represent the data.
We will be getting 64 positive and 63 negative values and answer should be -64, 63.)
No, because in two's complement, the most significant bit is the sign bit. 0000001 is +1, a positive number.
That is why the range of two's complement 7-bit numbers is -64 to 63, because 64 is not representable (it would be negative number otherwise).
The most negative number is 1000000. The leading 1 tells you it's negative, and to get the magnitude of the number, you flip all the bits (0111111), then add one (1000000 = 64). So the resulting number is -64 thru 63.
For largest positive integer in 2's complement use the formula
(2^(n-1)-1)
That is (2^(7-1)-1)=63
For the smallest use
-2^n-1
That is -2^7-1=-64

C++ char arithmetic overflow

#include <stdio.h>
int main()
{
char a = 30;
char b = 40;
char c = 10;
printf ("%d ", char(a*b));
char d = (a * b) / c;
printf ("%d ", d);
return 0;
}
The above code yields normal int value if 127 > x > -127
and a overflow value if other. I can't understand how the overflow value is calculated. As -80 in this case.
Thanks
The trick here is how numbers are represented. Look into 2's complement. 30 * 40 in binary is 1200 or 10010110000 base 2. But our char is only 8 bits so we chop off the leading 100 (and all the implied 0s before that). This leaves us with 1011000.
Note the leading 1. In 2s complement, how your computer probably stores the values, this indicates a negative number. 11111111 is -1, 11111110 is -2 and so on. If go down to 1011000 we get to -80.
That is, if we convert 1011000 to 2s complement we're left with -80.
You can do 2s complement by hand. Take the value, drop the leading sign bit and swap the other values. In this case 10110000 turns into 01001111 in binary this would be 79. Turn it negative and remove one more because we don't start at zero and we're at -80.
Char has only 1 byte. In this case 1200 is 0100 1011 0000 (binary).
For one byte you can only assign 8 bit, in your case: 1011 0000 (first 4 bits will be deleted). Now you have -80 (first bit shows if negative (1) or positive (0)).
Try with your calculator (programmer) and type 1200 decimal and switch from Qword to Byte and you can see what happens with your number.

NOT operation on integer value

I knew that ~ operator does NOT operation. But I could not make out the output of the following program (which is -65536). What exactly is happening?
#include <stdio.h>
int main(void) {
int b = 0xFFFF;
printf("%d",~b);
return 0;
}
Assuming 32-bit integers
int b = 0xFFFF; => b = 0x0000FFFF
~b = 0xFFFF0000
The top bit is now set. Assuming 2s complement, this means we have a negative number. Inverting the other bits then adding one gives 0x00010000 or 65536
When you assign the 16-bit value 0xffff to the 32-bit integer b, the variable b actually becomes 0x0000ffff. This means when you do the bitwise complement it becomes 0xffff0000 which is the same as decimal -65536.
The ~ operator in C++ is the bitwise NOT operator. It is also called the bitwise complement. This is flipping the bits of your signed integer.
For instance, if you had
int b = 8;
// b in binary = 1000
// ~b = 0111
This will flip the bits that represent the initial integer value provided.
It is doing a bitwise complement, this output may help you understand what is going on better:
std::cout << std::hex << " b: " << std::setfill('0') << std::setw(8) << b
<< " ~b: " << (~b) << " -65536: " << -65536 << std::endl ;
the result that I receive is as follows:
b: 0000ffff ~b: ffff0000 -65536: ffff0000
So we are setting the lower 16 bits to 1 which gives us 0000ffff and then we do a complement which will set the lower 16 bits to 0 and the upper 16 bits to 1 which gives us ffff0000 which is equal to -65536 in decimal.
In this case since we are working with bitwise operations, examining the data in hex gives us some insight into what is going on.
The result depends on how signed integers are represented on your platform. The most common representation is a 32-bit value using "2s complement" arithmetic to represent negative values. That is, a negative value -x is represented by the same bit pattern as the unsigned value 2^32 - x.
In this case, the original bit pattern has the lower 16 bits set:
0x0000ffff
The bitwise negation clears those bits and sets the upper 16 bits:
0xffff0000
Interpreting this as a negative number gives the value -65536.
Usually, you'll want to use unsigned types when you're messing around with bitwise arithmetic, to avoid this kind of confusion.
Your comment:
If it is NOT of 'b' .. then output should be 0 but why -65536
Suggests that you are expecting the result of:
uint32_t x = 0xFFFF;
uint32_t y = ~x;
to be 0.
That would be true for a logical not operation, such as:
uint32_t x = 0xFFFF;
uint32_t y = !x;
...but operator~ is not a logical NOT, but a bitwise not. There is a big difference.
A logical returns 0 for non-0 values (or false for true values), and 1 for 0 values.
But a bitwise not reverses each bit in a given value. So a binary NOT of 0xF:
0x0F: 00000000 11111111
~0x0F: 11111111 00000000
Is not zero, but 0xF0.
For every binary number in the integer, a bitwise NOT operation turns all 1s into 0s, and all 0s are turned to 1s.
So hexadecimal 0xFFFF is binary 1111 1111 1111 1111 (Each hexadecimal character is 4 bits, and F, being 15, is full 1s in all four bits)
You set a 32 bit integer to that, which means it's now:
0000 0000 0000 0000 1111 1111 1111 1111
You then NOT it, which means it's:
1111 1111 1111 1111 0000 0000 0000 0000
The topmost bit is the signing bit (whether it's positive or negative), so it gives a negative number.