Ace Caserya
Ace Caserya

Reputation: 2935

Using a size_t as limiter for a "for loop"

I'm using a C++ app on my s6 named CppDroid to make a quick program.

How do you use a size_t as limiter for a "for loop" on it's counter?

int c;

//... more codes here...

    for (c=0; c < a.used; ++c)

        //... more codes here...

The a.used is a number of used array that came from a solution to make a dynamic sized array

The error is: comparison of integer of different signs: 'int' and 'size_t' (aka unsigned int)

The for loop is one of an internal nested loops of the program so I want to maintain variable c as an "int" as much as possible.

I've seen examples about Comparing int with size_t but I'm not sure how it can help since it is for an "if" condition.

Upvotes: 3

Views: 5816

Answers (3)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145299

Regarding

comparison of integer of different signs: 'int' and 'size_t' (aka unsigned int)

… this is a warning. It's not an error that prevents creation of an executable, unless you've asked the compiler to treat warnings as errors.

A very direct way to address it is to use a cast, int(a.size).

More generally I recommend defining a common function to do that, e.g. named n_items (C++17 will have a size function, unfortunately with unsigned result and conflating two or more logical functions, so that name's taken):

using My_array = ...; // Whatever

using Size = ptrdiff_t;

auto n_items( My_array const& a )
    -> Size
{ return a.used; }

then for your loop:

for( int c = 0; c < n_items( a ); ++c )

By the way it's generally Not A Good Idea™ to reuse a variable, like c here. I'm assuming that that reuse was unintentional. The example above shows how to declare the loop variable in the for loop head.


Also, as Matteo Italia notes in his answer, it can sometimes be a good idea to manually optimize a loop like this, if measuring shows it to be a bottleneck. That's because the compiler can't easily prove that the result of the n_items call, or any other dynamic array size expression, is the same (is “invariant”) in all executions of the loop body.

Thus, if measuring tells you that the possibly repeated size expression evaluations are a bottleneck, you can do e.g.

for( int c = 0, n = n_items( a ); c < n; ++c )

It's worth noting that any manual optimization carries costs, which are not easy to measure, but which are severe enough that the usual advice to is to defer optimization until measurements tell you that it's really needed.

Upvotes: 2

Matteo Italia
Matteo Italia

Reputation: 126837

As long as a.used doesn't change during the iteration, a common idiom is:

for(int c=0, n=a.used; c<n; ++c) {
    ...
}

In this way, the cast happens implicitly, and you also have the "total number of elements" variable n handy in the loop body. Also, when n comes from a methods call (say, vec.size()) you evaluate it just once, which is slightly more efficient.1


1. In theory the compiler may do this optimization by itself, but with "complicated" stuff like std::vector and a nontrivial loop body it's surprisingly difficult to prove that it's a loop invariant, so often it's just recalculated at each iteration.

Upvotes: 7

Shoe
Shoe

Reputation: 76260

Just use std::size_t c instead of int c.

Upvotes: 10

Related Questions