简体   繁体   English

使用size_t的负整数是否安全?

[英]Is it safe to use negative integers with size_t?

I just saw some C++ code like this. 我刚看到一些像这样的C ++代码。 It was using a condition to decide whether to walk forward or backward through a std::vector . 它使用一个条件来决定是通过std::vector前进还是后退。 The compiler doesn't complain, but I thought size_t was unsigned. 编译器没有抱怨,但我认为size_t是无符号的。 Is this dangerous? 这有危险吗?

vector<int> v { 1,2,3,4,5 };    
bool rev = true;

size_t start, end, di;
if (rev) {
    start = v.size()-1;
    end = -1;
    di = -1;
}
else {
    start = 0;
    end = v.size();
    di = 1;
}

for (auto i=start; i!=end; i+=di) {
    cout << v[i] << endl;
}

It's well defined to use unsigned integers (and size_t is unsigned) this way, with wraparound: that behavior is guaranteed by the standard, as opposed to with signed integers, where it's not guaranteed by the standard. 通过这种方式很好地定义了使用无符号整数(并且size_t是无符号的),并且有回绕:标准保证了这种行为,而不是有符号整数,标准不保证这种行为。

It is however needlessly clever. 然而,这是不必要的聪明。

As a general rule, to avoid problems due to implicit wrapping promotions to unsigned, use unsigned integers for bit-level stuff, use signed integers for numbers. 作为一般规则,为了避免由于隐式包装促销到无符号的问题,使用无符号整数用于位级别的东西,使用有符号整数来表示数字。 Where you need a signed integer corresponding to size_t there's ptrdiff_t for you. 你需要一个对应于size_t有符号整数,你可以找到ptrdiff_t Define an n_items function with signed result, eg 定义带有签名结果的n_items函数,例如

using Size = ptrdiff_t;

template< class Container >
auto n_items( Container const& c )
    -> Size
{ return end( c ) - begin( c ); }

and you're set to go, no more sillywarnings from the compiler. 你已经准备好了,不再是编译器的愚蠢行为。


Instead of the too clever given code 而不是太聪明的给定代码

vector<int> v { 1,2,3,4,5 };    
bool rev = true;

size_t start, end, di;
if (rev) {
    start = v.size()-1;
    end = -1;
    di = -1;
}
else {
    start = 0;
    end = v.size();
    di = 1;
}

for (auto i=start; i!=end; i+=di) {
    cout << v[i] << endl;

do eg 做例如

const vector<int> v { 1,2,3,4,5 };    
const bool reverse = true;  // whatever

for( int i = 0; i < n_items( v );  ++i )
{
    const int j = (reverse? n_items( v ) - i - 1 : i);
    cout << v[j] << endl;
}

I can't speak to how safe that code is but I think it's a pretty poor style. 我不能说代码有多安全 ,但我认为这是一种非常糟糕的风格。 A better way would be to use iterators which support forward or reverse iteration. 更好的方法是使用支持正向或反向迭代的迭代器。

For example: 例如:

std::vector<int> v = { 1, 2, 3, 4, 5 };
bool rev = true;

if (rev)
{
    for (auto itr = v.rbegin(); itr != v.rend(); ++itr)
    {
        std::cout << *itr << "\n";
    }
}
else
{
    for (auto itr = v.begin(); itr != v.end(); ++itr)
    {
        std::cout << *itr << "\n";
    }
}

Whenever I need to deal with signed types, I always use: 每当我需要处理签名类型时,我总是使用:

typedef std::make_signed<std::size_t>::type ssize_t; // Since C++11

...as a signed alternative to std::size_t. ...作为std :: size_t的签名替代。

I appreciate this question is a few years old, but I'm hoping that will help others. 我很欣赏这个问题已经有几年了,但我希望能帮到别人。 Credit to moodycamel::ConcurrentQueue . 感谢moodycamel :: ConcurrentQueue

Is it safe to use negative integers with size_t? 使用size_t的负整数是否安全?

No, it is dangerous. 不,这很危险。 Overflow. 溢出。

size_t a = -1;
std::cout << a << "\n";

Output: 输出:

4294967295 // depends on the system, largest value possible here

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM