npn
npn

Reputation: 401

Signed arithmetic

I'm running this piece of code, and I'm getting the output value as (converted to hex) 0xFFFFFF93 and 0xFFFFFF94.

#include <iostream>

using namespace std;

int main()
{
    char x = 0x91;

    char y = 0x02;

    unsigned out;
    out = x + y;

    cout << out << endl;
    out = x + y + 1;
    cout << out << endl;
}

I'm confused about the arithmetic going on here. Is it because all the higher bits in out are taken to be 1 by default? When I typecast out to an int, I get the answers as (in int) -109 and -108. Any idea why this is happening?

Upvotes: 2

Views: 216

Answers (4)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158469

So there are a couple of things going on here. One, char can be either signed or unsigned, in your case it is signed. Two assignment will covert the right hand side to the type of the left hand side. Using the right warning flags would help, clang with the -Wconversion flags warns:

warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
out = x + y;
    ~ ~~^~~

In this case to do this conversion it will basically add or subtract the unsigned max + 1 to the number to be converted.

We can see the same results using the limits header:

#include <limits>

//....
std::cout << std::hex <<  (std::numeric_limits<unsigned>::max() + 1) + (x+y) << std::endl ;
//...

and the result is:

ffffff93

For reference the draft C++ standard section 5.17 Assignment and compound assignment operators says:

If the left operand is not of class type, the expression is implicitly converted (Clause 4) to the cv-unqualified type of the left operand.

Clause 4 under 4.7 Integral conversions says:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

which is equivalent to adding or subtracting UMAX + 1.

Upvotes: 4

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

A plain char usually also represents a signed type! Since compatibility reasons with C syntax, this isn't specified further, and may be compiler implementation dependent. You always can make it distinct signed arithmetic behavior, by explicitly specifying the signed / unsigned keywords.

Try replacing your char definitions like this

unsigned char x = 0x91;
unsigned char y = 0x02;

to get the results you expect!

See the fully working sample here.

Upvotes: 2

stefaanv
stefaanv

Reputation: 14392

C++ doesn't specify whether char is signed or unsigned. Here they are signed, so when they are promoted to int's, the negative value is used which is then converted to unsigned. Use or cast to unsigned char.

Upvotes: 0

unxnut
unxnut

Reputation: 8839

The negative numbers are represented internally as 2's complement and hence, their first bit is a 1. When you work in hex (and print in hex), the significant bits are displayed as 1's leading to numbers like you showed.

Upvotes: 0

Related Questions