-1

The code causing the problem in question is shown below:

for(size_t i = 10; i >= 0; i--){
   cout << i  << ", ";
}

this outputs: 4, 3, 2, 1, 0, 18446744073709551615,

and then the program returns a segmentation fault for the obvious reason that it attempts to access my the items at a ridiculous index.

why does the counter not stop at 0?

EDIT: I was using a webcompiler for an assignment. It didn't provide any warnings. Generally I develop locally and then just paste in what I've made because I have had compiler issues before. Good to know I wasn't being completely dumb even though the issue was small. Thanks for all the help! Just figured i'd adda little additional information added after many of the answers were given.

4 Answers4

2

size_t is an unsigned integral. This means that i can never be negative. When i is equal to 0, and you subtract 1, it will become a very large number, not -1.

The condition i >=0 basically says keep running this loop until i is less than zero. Because of the type of i, this condition is never met.

This is something your compiler could probably point out to you. I'm not sure which compiler you are using. But for example, if you are using gcc, you can add the flag -Wsign-compare-Wtype-limits.

Edit: Changed to proper gcc flag. Credits go to @Deduplicator

kill -9
  • 159
  • 1
  • 9
1

When you use a for loop to count form zero to nine, you do the following:

for(int i = 0; i < 10; i++){
   cout << i << endl;
}

Note that the condition of this loop is i < 10. At the end of the ninth iteration, i is incremented (i++) then checked (i < 10).

In your case, the type of i is size_t which is unsigned (aka can't be negative). Because of underflow, once i-- is called, i goes from 0 to size_t's maximum value. As this value is positive, the condition returns true and your for loop continues.

How to fix this?

Use a int instead. Size_t is generally used to represent the size of a container, no need to have it here :D.

Vélimir
  • 409
  • 3
  • 12
  • 1
    There might be a legitimate reason to keep with `size_t` in the general case, even though there certainly isn't is this simplified test-case. – Deduplicator Sep 23 '20 at 22:24
1

Many compilers will warn you if a comparison is always trivially true (or false).
In this case, an unsigned type like size_t can never hold a sub-zero value.

Of course, you must profess interest in getting warned, paying heed is optional.

For demonstration purposes, see the following program compiled on coliru using gcc and clang

int main() {
    for (unsigned i = 10; i >= 0; i--)
        /**/;
}

If you want to work on that whole range, and stay with the single unsigned loop-variable, rearranging a bit gets it done:

for (size_t i = 11; i-->0; )
    /**/;

Of course, i-->0 can be simplified to i--, but then I couldn't link "What is the "-->" operator in C++?".

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
0

In this case size_t is unsigned and obviously it goes to maximum value after being decreased by 1 when being 0. And possibly you use this counter i some where in your code to access an array element and then it gets out of boundary, so the segmentation fault!

One simple solution looks like:

for(size_t i = 10; i--;){
   std::cout << i  << ", ";
}

In this way the loop will defiantly stop at zero!

AKL
  • 1,367
  • 7
  • 20