1

I am attempting to write a program which loops through all ASCII characters, selects those which are letters, appends them to a string and then outputs this string. I have written the following code:

#include <iostream>
#include <string>
#include "ctype.h"

using namespace std;

int main()
{
   string str;

   for (char k = 0; k <= 255; k++) 
       if (isalpha(k) != 0) {
          str += k;
   }

   cout << str << '\n';
}

However, when I run this code I get a 'bad_alloc' error, which to my understanding means I ran out of memory. Thus, I must have done something terribly wrong in my code. I am very new to C++ in general, could someone point out my (possibly many) mistakes?

Anon
  • 25
  • 1
  • 6

3 Answers3

4

You should enable all warnings when you compile your code (-Wall -Wextra). Doing so would result in the following message by the compiler:

clang:

result of comparison of constant 255 with expression of type 'char' is always true [-Wtautological-constant-out-of-range-compare]

gcc:

warning: comparison is always true due to limited range of data type [-Wtype-limits]

Depending on the compiler and the target platform the signedness of char depends can vary. The defaults for ARM and PowerPC are typically unsigned, the defaults for x86 and x64 are typically signed.

The range of char, if signed, is -128 to 127, to be platform-independent, you need to ensure that you use unsinged char, but even then you would have the problem that <=255 would produce the same bad_alloc error, as the maximum value of a unsigned char is 255, so you have to use `k < 255;':

for (unsigned char k = 0; k < 255; k++)
t.niese
  • 39,256
  • 9
  • 74
  • 101
  • That's odd. When compiling my code I use '-Wall' and '-Werror' so that it gives me all warnings and errors, however, it gives me none in this case. – Anon Sep 15 '19 at 18:19
  • @Anon I always compile with at least `-Wextra -Wall -pedantic` – t.niese Sep 15 '19 at 18:21
  • Even doing this it did not give me any warnings. Should I be worried that there is something off about my compiler? I use the GNU g++ compiler. – Anon Sep 15 '19 at 18:55
  • Re: "the range of char is -128 to 127" -- that is true **if** `char` is signed **and** it has 8 bits. With some compilers that's not the case. – Pete Becker Sep 15 '19 at 19:41
  • @Anon even with `-Wextra` because that should result in a warning for both cases `char` beeing signed and unsigned, because `k <= 255` would always be true in both cases. Which compiler do you use? And on which platform do you compile? – t.niese Sep 16 '19 at 05:42
1

Change for (char k = 0; k <= 255; k++) to for (int k = 0; k <= 255; k++) then it will be fine.

Reason: Char on the system is signed character, hence it's range is 2^n - 1 to -(2^n) - 1 where n is 8 (you can check it by printing macro CHAR_BIT).

So when the loop for k reaches 127 and goes for the next value, it becomes -128 as the value wraps around & then it becomes the infinite loop.

You can verify this by:

char c=127;
char d=c+1;

printf("%d\n",d);

OUTPUT: -128

Gaurav
  • 1,570
  • 5
  • 17
1

On many platforms, char is signed. That means it goes to 127 then "overflows".

Overflowing has undefined behaviour, but sometimes that looks like a "wrap-around" to a negative value. The result is that k will always be less than 255, so your loop will never end, and you'll keep trying to add characters to the string forever, or until you run out of memory (boom).

Indeed even if you use an unsigned char, you're still never going to get above 255.

Use an int instead.

Your call to isalpha also has undefined behaviour, for similar reasons (refer to the documentation for functions that you use).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055