Is it safe to use negative integers with size_t?

后端 未结 4 1785
旧巷少年郎
旧巷少年郎 2021-02-20 17:52

I just saw some C++ code like this. It was using a condition to decide whether to walk forward or backward through a std::vector. The compiler doesn\'t complain, b

相关标签:
4条回答
  • 2021-02-20 18:23

    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";
        }
    }
    
    0 讨论(0)
  • 2021-02-20 18:29

    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.

    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. Define an n_items function with signed result, e.g.

    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 e.g.

    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;
    }
    
    0 讨论(0)
  • 2021-02-20 18:42

    Is it safe to use negative integers with 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
    
    0 讨论(0)
  • 2021-02-20 18:44

    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.

    I appreciate this question is a few years old, but I'm hoping that will help others. Credit to moodycamel::ConcurrentQueue.

    0 讨论(0)
提交回复
热议问题