2

I have a array consisting of chars like [1,2,3,4,5,.,..] and I have a loop that looks like

  for (size_t i = 0; i < size; ++i)
    os << data[i]; // os is std::ostream&

This loop prints the array in the correct order without any errors. But when I use this loop to print it backwards

  for (size_t i = (size - 1); i >= 0; --i)
    os << data[i];

I get a segmentation fault error. Any reason why this can happen?

Sarah Hyland
  • 267
  • 3
  • 9
  • 1
    `size_t`, as you know, is an unsigned value. Can you think of any unsigned value that is negative? – Sam Varshavchik Apr 14 '18 at 19:20
  • Unfortunately, I don't have any control over the type. Is there another way this could be made to work? – Sarah Hyland Apr 14 '18 at 19:25
  • I would use a type int for i, but if you can't. Then I guess you can use a break statement once i = 0 after the os << data[i]. – Alex Apr 14 '18 at 19:26
  • Of course there's a way to make it work using `size_t`. You just have to understand that `size_t` cannot be negative, and adjust your logic accordingly. You can use a do-while loop, with the comparison done using a post-decrement operator, or still use a `for` loop, but compare for `> 0`, and decrement at the beginning of the loop, not at the end. – Sam Varshavchik Apr 14 '18 at 19:30

3 Answers3

4

The condition i >= 0 is always true (because size_t is an unsigned type). You've written an infinite loop.

Doesn't your compiler warn you about that? I know g++ -Wextra does here.

What you can do instead is this:

for (size_t i = size; i--; ) {
    os << data[i];
}

This uses post-decrement to be able to check the old value of i, which allows the loop to stop just after i = 0 (at which point i has wrapped around to SIZE_MAX).

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • I followed the instructions from here: https://stackoverflow.com/questions/30834885/how-to-print-an-array-backwards – Sarah Hyland Apr 14 '18 at 19:21
  • It doesn't give any warning unfortunately. – Sarah Hyland Apr 14 '18 at 19:21
  • What part of those instructions advised you to use a `size_t`? – Sam Varshavchik Apr 14 '18 at 19:22
  • @SarahHyland What compiler are you using? – melpomene Apr 14 '18 at 19:22
  • G++ C++11, it has -Wall and -Wextra enabled. – Sarah Hyland Apr 14 '18 at 19:23
  • @SarahHyland [Can't reproduce](https://tio.run/##NY7LCoMwFET3@YqBgi8quK2v3@imUEKM9oJGSWIpLf5600TpLObegcMwYlnyQQjnTqTEuHYSNc3GasmnlrHVkBpgbFeWht7ybivGSFlMnFQSHq4HcYZ4cI0s8@GZ4sPgRT2SkBFFO4S2QZFCS7tqhaLaoX7WSI5iEBpcKn8CWCHP6V8VtE8Q82pR157xFt9UfLRsbHPuK/qRD8blVz6O3uXLav4D). It says `.code.tio.cpp:7:26: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]` – melpomene Apr 14 '18 at 19:27
  • This works but for some reason, it leaves out one character which was the first character in the normal array. For example if the normal array is 123456, it prints 65432. – Sarah Hyland Apr 14 '18 at 19:41
2

size_t is unsigned int so it always remain positive, so your loop is an infinite loop

Abhishek Keshri
  • 3,074
  • 14
  • 31
2

You can use a C++ for-in loop to avoid the problem. Example:

#include <iostream>
#include <vector>
#include <boost/range/adaptor/reversed.hpp>

using std::vector;
using std::cout;
using boost::adaptors::reverse;

int main()
{
  auto v = vector<char>{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X' };

  char const* sep = "";
  for (auto c : v)
  {
    cout << sep << c;
    sep = " ";
  }
  cout << "\n";

  sep = "";
  for (auto c : reverse(v))
  {
    cout << sep << c;
    sep = " ";
  }
  cout << "\n";
}
Eljay
  • 4,648
  • 3
  • 16
  • 27