0

This should simply be adding 1 to an unsigned int: prev = nums[nextIndex + 1]; but it gives a warning saying

Arithmetic overflow: Using operator '+' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '+' to avoid overflow

But I'm not using any 8 byte values, they are all 32-bit integers... Why is it casting stuff into 8 byte values for me?

I'm doing some questions on LeetCode so here is the full code for the question I'm working on, just rotating a vector of ints:

    void rotate(std::vector<int>& nums, int k) {
        k %= nums.size();
        if (k > 0) {
            unsigned int offsetCounter = 0; 
            int prev;
            int next = nums[0];
            for (unsigned int i = 0; i < nums.size(); i++) {


                int f = k * i;

                unsigned int nextIndex = ((unsigned int)((unsigned int)k * ((unsigned int)i + (unsigned int)1)) + (unsigned int)offsetCounter) % (unsigned int)nums.size();

                if (nextIndex == offsetCounter) {
                    offsetCounter++;
                    prev = nums[nextIndex + 1];
                }
                else
                {
                    prev = nums[nextIndex];
                }
                nums[nextIndex] = next;
                next = prev;
            }
        }
    }

nextIndex also gave the same warning and the only thing that got rid of it was casting everything to an unsigned int. I don't understand why it says I am using 8 byte values when I am definitely not using 8 byte values. I've ignored warnings like this in the past but LeetCode takes them very seriously. Thank you.

Tristan367
  • 25
  • 6
  • Step 1: uses the same type in the addition `nextIndex + 1` --> `nextIndex + 1u` (`unsigned + int` vs `unsigned + unsigned`). Perhaps the mixed addition hints to the complier you seek an arithmetic sum. Might as well simplify other code too: `(unsigned int)1` --> `1u`. – chux - Reinstate Monica Jul 18 '21 at 23:22
  • 2
    Including the compiler error number (C26451, I think) and searching for that here on SO will give you several similar questions that should clue you in to the problem. (Which is that the parameter to `vector::operator[][` is `std::size_t`, which is 64 bits.) – 1201ProgramAlarm Jul 18 '21 at 23:26
  • @1201ProgramAlarm Good observation, Better to use `size_t` for array indexing and size calculations. – chux - Reinstate Monica Jul 18 '21 at 23:27

2 Answers2

1

Vector indexes (and std::vector::size()) are size_ts, not unsigned ints, and that's where your problems are coming from.

To fix this, declare all your unsigned int variables as size_t and get rid of all those casts:

void rotate(std::vector<int>& nums, size_t k) {
    k %= nums.size();
    if (k > 0) {
        size_t offsetCounter = 0; 
        int prev;
        int next = nums[0];
        for (size_t i = 0; i < nums.size(); i++) {
            size_t nextIndex = (k * i + 1 + offsetCounter) % nums.size();

            if (nextIndex == offsetCounter) {
                offsetCounter++;
                prev = nums[nextIndex + 1];
            }
            else
            {
                prev = nums[nextIndex];
            }
            nums[nextIndex] = next;
            next = prev;
        }
    }
}

Live demo

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • Oh ok thank you so much, I suspected it had something to do with vector. This actually fixed the error and LeetCode accepted my answer. Thanks again! – Tristan367 Jul 18 '21 at 23:48
1

operator[] in std::vector is defined as

constexpr reference operator[]( size_type pos );

plus several similar overloads, all taking an argument of type size_type defined by std::vector. Cppreference.com says about this type this:

Unsigned integer type (usually std::size_t)

The explanation about std::size_t (part):

std::size_t is commonly used for array indexing and loop counting. Programs that use other types, such as unsigned int, for array indexing may fail on, e.g. 64-bit systems when the index exceeds UINT_MAX or if it relies on 32-bit modular arithmetic.

When indexing C++ containers, such as std::string, std::vector, etc, the appropriate type is the member typedef size_type provided by such containers. It is usually defined as a synonym for std::size_t.

So: std::vector is indexed using a type that is usually equivalent to std::size_t, which on your machine is a 64-bit unsigned int.

So, if you want the warning gone, you can define nextIndex as a 64-bit unsigned integer, e.g.

  • unsigned long nextIndex or
  • size_t nextIndex;
  • std::vector<int>::size_type nextIndex;

or force the conversion by using a constant that is of type unsigned ling long:

prev = nums[nextIndex + 1ull];
zkoza
  • 2,644
  • 3
  • 16
  • 24