Why am I getting errors when using unsigned integers in an expression with C ++?

Considering the following piece of code (pseudo C ++):

float x=100, a=0.1;
unsigned int height = 63, width = 63;
unsigned int hw=31;
for (int row=0; row < height; ++row)
{
    for (int col=0; col < width; ++col)
    {
        float foo = x + col - hw + a * (col - hw);
        cout << foo << " ";
    }
    cout << endl;
}

      

The foo values ​​are screwed in half the array, where (col-hw) is negative. I realized that col is int and in the first place, that this part of the expression is converted to int and becomes negative. Unfortunately this does not appear to be happening, I am getting a signed value overflow and I have no idea why.

How can I solve this problem? Use broadcasts for all or part of an expression? What type of butts (C-style or static_cast <...>)? Is there an overhead of using casts (I need this to work fast!)?

EDIT: I changed all my unsigned ints to regular ones, but I'm still wondering why I got this overflow in this situation.

+2


a source to share


5 answers


Unsigned integers implement unsigned arithmetic. Unsigned arithmetic is modular arithmetic. All values ​​are adjusted modulo 2 ^ N, where N is the number of bits in the representation of unsigned values.

In simple words, unsigned arithmetic always produces non-negative values. Whenever an expression must result in a negative value, the value actually wraps around 2 ^ N and becomes positive.



When you mix signed and unsigned integer in the [sub] expression, the assigned arithmetic "wins"; calculations are performed on an unsigned domain. For example, when you execute col - hw

, it is interpreted as (unsigned) col - hw

. This means that for col == 0

and hs == 31

you will not get -31

as a result. Instead, you get UINT_MAX - 31 + 1

, which is usually a huge positive value.

Having said that, I should point out that it is always useful in my opinion to use unsigned types to represent inherent non-negative values. In fact, in practice, most (or at least half) of the integer variables in a C / C ++ program must be of unsigned types. Your attempt to use unsigned types in your example is well founded (if you understand the intent correctly). Moreover, I would use unsigned

for col

androw

... However, you must keep in mind how unsigned arithmetic works (as described above) and write your expressions accordingly. In most cases, the expression can be rewritten so that it does not cross the boundaries of the unsigned range, that is, in most cases there is no need to explicitly cast anything to a signed type. Otherwise, if you need to work with negative values, in the end, the correct signed type approach should solve the problem.

+7


a source


How to make height

, width

and hw

signed ints? What are you really typing by making them unsigned? Mixing signed and unsigned integers always causes problems. At first glance, at least it looks like you're not getting anything using unsigned values ​​here. This way you can also make them signed and save yourself the trouble.



+2


a source


You have rules for converting backwards - when you mix signed and unsigned versions of the same type, the signed operand is converted to unsigned.

+1


a source


If you want this to be fast, you must statically_map all unsigned values ​​before starting the loop and use their int versions, not unsigned int versions. You can still require unsigned inputs and then just drop them in your algorithm path to keep the required domain for your function.

0


a source


The throws will not be performed automatically - aerobic transmission is still used. A common example is int / int = int, even if data is lost without converting to float. I would use a signed int if this is not possible due to the INT_MAX being too small.

0


a source







All Articles