-2

When i use j>=num-i in the inner loop ,program will throw a segmentation fault.

#include <iostream>
using namespace std;

int main(){
    cout << "Enter the number of rows: ";
    int num;
    cin >> num;
    
    for (size_t i = 1; i <= num; i++)
    {
        char ch[num];
        for (size_t r = 0; r < num; r++)
        {
            ch[r]='.';
        }
        for (int j = num-1  ; j >=num-i; j--)   
        // when i = num , this part will throw a segmetation fault.
        {
             ch[j]='*';    
 
        }
        ch[num] = '\0';
        cout << ch <<endl;
        
    }
    
    return 0;
}

But when i use j >= 0 ,and add an if sentence the program will work,why is that?

#include <iostream>
using namespace std;
int main(){
    cout << "Enter the number of rows: ";
    int num;
    cin >> num;
    for (size_t i = 1; i <= num; i++)
    {
        char ch[num];
        for (size_t r = 0; r < num; r++)
        {
            ch[r]='.';
        }
        
        for (int j = num-1  ; j >=0; j--) 
        {
           if (j>=num-i)
           {
             ch[j]='*';
           }
        }
        ch[num] = '\0';
        cout << ch <<endl;
    }
    return 0;
}

why i cannot use j>=num-i as the judge condition in the for loop? Is something i have missed?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
wuqian
  • 1
  • 2
  • 9
    Variable length arrays as that char ch[num+1]; is not a standard C++ feature. – Vlad from Moscow Aug 30 '23 at 13:56
  • 3
    Moreover the array does not contain a string. So this statement cout << ch < – Vlad from Moscow Aug 30 '23 at 13:58
  • 1
    https://stackoverflow.com/questions/2037209/what-is-a-null-terminated-string But first I would go for: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – pptaszni Aug 30 '23 at 14:08
  • 3
    PSA: `std::string` exists and you should probably use it. C strings are *absolutely* no fun. – tadman Aug 30 '23 at 14:08
  • either way the code has undefined behavior and anything could happen. – 463035818_is_not_an_ai Aug 30 '23 at 14:12
  • 2
    `num - i` is `unsigned` (as `i`). and when `num == i`, `j >= num - i` becomes `j >= 0u` which is always `true` (`j` is also converted to `std::size_t`). then you access `ch[-1]` – Jarod42 Aug 30 '23 at 14:12
  • 1
    Don't mix unsigned with signed in comparison. Compiler might warn you with correct level. – Jarod42 Aug 30 '23 at 14:14
  • An array like `char ch[num];` (putting aside the non-standard and, frankly, dangerous use of a runtime value to set the array size) has `num` elements, which can be accessed with index values running from `0` to `num-1`. `ch[num] = '\0'` uses an invalid index. The behavior of the program is undefined. – Pete Becker Aug 30 '23 at 14:18
  • @Jarod42 THks , i find my fault – wuqian Aug 30 '23 at 14:21
  • 1
    `char ch[num];` where `num` is a variable (not a compile time constant) is not valid in standard C++ (but, unfortunately, a few too many compilers support it as a *non-standard* extension). One contributor to your problem is that `ch[num] = '\0';` on an array with `num` elements always writes one past the end. – Peter Aug 30 '23 at 15:51

1 Answers1

1

You are trying to use a variable length array

char ch[num];

But variable length arrays are not a standard C++ feature.

This statement

ch[num] = '\0';

overwrites memory outside the array because the valid range of indices for the array is [0, num ).

So already the both your programs invoke undefined behavior.

Also in this for loop

for (int j = num-1  ; j >=num-i; j--) 

the expression num-i has the type size_t due to the type of the variable i and the usual arithmetic conversions. So the left operand that is j in this condition j >=num-i also is converted to the type size_t. Assigning to it the value -1 by means of this expression j-- converts it to a very big value of the type size_t. As a result again using this value results in accessing memory outside the array.

Try this statement

std::cout << static_cast<size_t>( -1 ) << '\n';

Its output might look like

18446744073709551615

In the for loop in the second program

for (int j = num-1  ; j >=0; j--) 

there will be compared values -1 and 0 of the type int in this condition j >=0. So the loop will be interrupted correctly.

Instead of using a variable length array you should use standard class std::string.

It seems you mean something like the following

#include <iostream>
#include <string>

int main() 
{
    while ( true )
    {
        std::cout << "Enter the number of rows (0 - exit): ";

        size_t n;

        if ( not ( std::cin >> n ) or ( n == 0 ) ) break;

        std::cout << '\n';

        for ( size_t i = 0; i < n; i++ )
        {
            std::string s( n - i - 1, '.' );
            s.append( i + 1, '*' );
            std::cout << s << '\n';
        }

        std::cout << '\n';
    }
}

The program output might look like

Enter the number of rows (0 - exit): 10

.........*
........**
.......***
......****
.....*****
....******
...*******
..********
.*********
**********

Enter the number of rows (0 - exit): 0
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335