Reputation: 13575
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
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
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
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