user1899020
user1899020

Reputation: 13575

Is it safe to use size_t to shift vector index?

I prefer to use size_t to deal with vector index. But when shifting index, is it safe? For example,

size_t n = 10000000;
vector<int> v(n);

size_t i = 500000;
size_t shift = 20000;
int a = v(i - (-1) * shift); // Is this ok? what is `(-1) * shift` type, size_t?
int b = v(-shift + i); // Is this ok? what is `-shift` type, size_t?

Upvotes: 1

Views: 131

Answers (3)

Petr Skocik
Petr Skocik

Reputation: 60067

Surely, you meant v[...] instead of v(); std::vector has no operator(int).

Anyway, empirically,

#include <iostream>
using namespace std;
int main(){
    unsigned foo = 1;
    cout<<(-1)*foo<<'\n';
    cout<<-foo<<'\n';
    cout<<foo*(-1)<<'\n';
    cout<<static_cast<int>(-foo)<<'\n';
    cout<<static_cast<int>(foo)*-1<<'\n';
}

yields:

4294967295
4294967295
4294967295
-1
-1

ergo a negated unsigned or an unsigned multiplied by -1 overflows by wrapping around its maximum value (this should be the theoretical behavior too).

As for passing size_t to http://en.cppreference.com/w/cpp/container/vector/operator_at, if by chance std::vector<T>::size_type isn't size_t (unlikely but possible), passing a size_t within the bounds of your vector's size() should be safe and not lead to UB, as size_t must be large enough to index an array of any size.

Upvotes: 0

vsoftco
vsoftco

Reputation: 56557

Multiplying a size_t with (-1) is safe, it wraps around the maximum value of size_t, as size_t is an unsigned type. So (-1) * shift is the same as std::numeric_limits<size_t>::max-shift+1.

Upvotes: 1

Sam Varshavchik
Sam Varshavchik

Reputation: 118350

Negating an unsigned quantity is a valid operation. Section 5.3.2 of C++11:

The negative of an unsigned quantity is computed by subtracting its value from 2^n , where n is the number of bits in the promoted operand. The type of the result is the type of the promoted operand.

So, this is "safe", in so far as this is defined behavior.

Upvotes: 2

Related Questions