views:

156

answers:

4

I'm reviewing a C++ project and see effectively the following:

std::vector<SomeType> objects;

//then later
int size = (int)objects.size();
for( int i = 0; i < size; ++i ) {
    process( objects[i] );
}

Here's what I see. std::vector::size() returns size_t that can be of some size not related to the size of int. Even if sizeof(int) == sizeof(size_t) int is signed and can't hold all possible values of size_t. So the code above could only process the lower part of a very long vector and contains a bug. The right way would be to use size_t for both the size variable and the loop index.

That said I'm curious of why the author might have written this?

My only guess is that first he omitted the (int) cast and the compiler emitted something like Visual C++ C4018 warning:

warning C4018: '<' : signed/unsigned mismatch

so the author though that the best way to avoid the compiler warning would be to simply cast the size_t to int thus making the compiler shut up.

Is there any other possible sane reason for that C cast?

+8  A: 

I would say that the overwhelming use of C casts in both C and C++ is simply to make the compiler shut up, with little or no effort given to trying to understand what it is telling you. Sad, but true.

anon
A lot of the errors are trivial, meaningless in context, or unreadable. Makes sense a lot of people's reaction will be 'just shut up'.
Jay
@Jay That isn't true. Most errors are meaningful, and applying a cast is almost always the wring way of dealing with them. My own motto is - "if it needs a cast, it's wrong".
anon
A: 
unsigned int size = (int)objects.size();
for( unsigned int i = 0; i < size; ++i ) {
    process( objects[i] );
}
Андрей Костенко
What? Why not use `size_t` directly? Why still cast to `int`?
Georg Fritzsche
What? This is even worse. The expected type for the size variable is size_t, what's the point of going to unsigned int?
unwind
size_t could be bigger than unsigned int
sharptooth
+7  A: 

No, that is probably the reason. Plus the fact that the vector would probably never be so long that it would risk truncating the size (the app. developer would know that).

And... maybe in some parts of the program he actually compared "size" with something else that was int-typed, so making size a "size_t" type would fix it in one place, but break it somewhere else.

Virgil
+3  A: 

The obvious answer would be to use:

size_t size = objects.size();
for( size_t i = 0; i < size; ++i ) {
    process( objects[i] );
}

or to be pedantically correct:

typedef std::vector<SomeType>::size_type s_t;
s_t size = objects.size();
for (s_t i=0; i<size; ++i)
    process(objects[i]);

OTOH, unless you're sure you need to write the loop yourself, you're generally better off using an algorithm:

std::foreach(objects.begin(), objects.end(), process);
Jerry Coffin
In the first version you again cast to int.
sharptooth
@Sharptooth:Oops -- I copied his code and meant to fix it, but missed that. Thanks for pointing it out.
Jerry Coffin