1

I was watching my friend try to solve a programming challenge and at one point, his code looked like this:

#include <iostream>
#include <string>

using namespace std; 

int main(){ 
//Prompt user to enter string
const string SPACE {" "}; 
string input;

cout << "Please enter String you would like to see in a pyramid: "; 
getline(cin, input);

//Iterate string
for(int i {0}; i < input.length(); i++){ //Going through each character in string...
    for(int j {0}; j <= i; j++){ //Going through each character in string from 0 to i...
        cout << input[j];
    }
    for (int k {i}; k < input.length(); k--){ //Going backwards from string.length() to 0
        cout << input[k - 1];
    }
    cout << endl;
    }
}

The question I have is, why does the third for loop (last loop) not result in an infinite loop? k = 0 as the initial condition for the first iteration (since i = 0), and k is decremented by 1 for each iteration. Since the terminating condition should theoretically ALWAYS be false (k should always be less than input.length() for a positive integer length string), why does this loop terminate?

Kevin
  • 21
  • 3
  • 1
    Even if this *does* work, I'm 90% sure it's undefined behavior. Tell your friend his code might fail at any moment. – Silvio Mayolo Jun 04 '21 at 04:22
  • Good point! I incorrectly assumed that it would actually result in a segfault.. I wonder why it doesn’t do that instead? Seems like a segfault situation. – Kevin Jun 04 '21 at 04:28

2 Answers2

5

Note the comparison k < input.length(), where the input.length() returns unsigned string::size. If the k is negative, then the int will be converted and so its negative value will instead become a positive value. If the k was -1 at that time, then this value will be the biggest value possible for the string::size. Try to print out the values and see for yourself.

For example:

int main () {
    int i = -1;
    size_t s = 10;
    std::cout << (i > s) << std::endl;
}
// Prints 1, which means the (i > s) is true
rawrex
  • 4,044
  • 2
  • 8
  • 24
3

input.length() returns an unsigned value (size_t). This results in k being promoted (converted) to an unsigned value, and then comparison is made.

When k is -1, it will be promoted to an Very Large Positive Number, which will not be less than the string length.

However, even before this happens, you access input[-1], which results in undefined behavior (possibilities include a crash, display of a garbage value, or the program appearing to work properly).

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • Thank you very much! Just as a follow-up, why is the conversion done from int to an unsigned value for the purposes of the comparison? Why not convert the size_t to a signed value instead? – Kevin Jun 04 '21 at 04:26
  • 1
    @Kevin Because that's the way the language is defined to behave. – 1201ProgramAlarm Jun 04 '21 at 04:28
  • Makes sense, although it is curious to me that they don’t define it the other way around since it would seemingly avoid surprising results like these. – Kevin Jun 04 '21 at 04:33
  • 1
    @Kevin you would otherwise have had the surprise of a large size becoming a negative value. ;) – spectras Jun 04 '21 at 04:38
  • Good point! I suppose surprises like these are just an unavoidable part of the fun :) – Kevin Jun 04 '21 at 04:41