Something that puzzles me in the following simple program:

#include <iostream>
using namespace std;

int main()
{
   int row;
   cout << "enter row: ";
   cin >> row; 
   int K[row], m[row][5];   
         
    cout << "Enter all the " << row << " K values:\n";
    for (int i=0;i<row;i++)
        cin >> K[i]; 
    cin.ignore(10,'\n');
    cout << "1st verification: K[0]=" << K[0] << endl << endl;  //1st verification of K[0]
      
    for (int i=0,j=0; i<row,j<5; i++,j++)
    {
        m[i][j]=2;
        cout << "2nd verification: K[0]=" << K[0] << endl;  //2nd verification of K[0] (watch: diffferent from above when row=4)
     }   
   cin.get(); 
   return 0;
}

The puzzle is, when the input value for "row" is 4 (other values seem to pose no problem), then in the 2nd verification of the K[0] value (run 5 times, the last time the K[0] will be DIFFERENT from before!--even though it's not changed anywhere: Output (Notice the last line, K[0] is no longer 10):

enter row: 4
Enter all the 4 K values:
10 20 30 40
1st verification: K[0]=10

2nd verification: K[0]=10
2nd verification: K[0]=10
2nd verification: K[0]=10
2nd verification: K[0]=10
2nd verification: K[0]=2

Note if

m[i][j]=2;

is changed to something not involving the indices, it's fine.
Also, if, instead of the short cut simultaneous loop

for (int i=0,j=0; i<row,j<5; i++,j++)

we use nested loop

for (int i=0;i<row;i++)
    for (int j=0;j<5;j++)

it's also fine.

So what is the problem, and why does it have problem only for input value row=4, not row=3 or 5 or other values?

Thanks in advance for solving the puzzle for me.

Your problem is the assignment beyond the end of the array.

You wrote this for (int i=0,j=0; i<row,j<5; i++,j++) And that means : do i<row, ignore the result and test j<5.

Therefore when you get to this m[i][j]=2; you will definitely run m[4][4]=2; regardless of row.
That means you assign a memory location outside of m. (which is your particular case turns out to be K).

You needed to write: for(int i=0,j=0;i<row && j<5;i++,j++)

Edited 6 Years Ago by StuXYZ: n/a

Could you please be more specific? assignment to K or to m? Note that the K[0] value is already determined in line 13. Also, in lines 17~21, the m[j] has nothing to do with K[0].

Sorry sqw, I was amending my post which your were writing your comment....

If you write beyond that edge of an array, the memory is likely to be used for something else. If that is the case, then your are able to change absolutely any variable in your code. It comes in a number of guises, some by mis-controlling a loop, others by not controlling user input and a buffer becomes overly full.

Thanks! It indeed works with the &&. So that means with the "&&", as long as j<5 is true, then i++ will happen, so m's i-index went beyond the max number 3? Your conclusion that the extra m[4][4] was assigned to K is excellent and really makes sense.

A question about the simultaneous loops: is the above (after your correction) equivalent to

for (i=0; i<row; i++)
   for (j=0; j<5; j++)
      m[i][j]=2;

?
If not, what is the exact order of the loop iteration?
Thanks a ton.

After making some tests, I think I can answer my own question above, though not sure if right:

for (int i=0,j=0; i<a && j<b; i++,j++)

will result in the final values of i, j being the same, and equal to the smaller one of a and b.

for (int i=0,j=0; i<a, j<b; i++,j++)

which seems to be equivalent to

for (int i=0,j=0; i<a || j<b; i++,j++)

will result in i, j having the same final value, which equals the larger one of a and b.

Because i, j have the same initial value (0), they will always be the same during the iterations, as each step both increases simultaneously by 1.

Am I right? It seems combining i, j in one for-loop statement is not a good idea.

Well done, you are correct that in many of your statements.

But note that i<a,j<b is NOT equivalent to i<a || j<b . Because in the first case the i<a test is ignored. e.g for(int i=0,j=0;i<10,j<5;j++,i++) stops at j=5, but if you write
|| then it stops at j=10.

Also, note that combining i and j in one loop can be exactly what you want in some circumstances, e.g determining the trace of a matrix, you only need the diagonal elements. However, more commonly you need two nested loops.

[Note: very often if you need only one loop, you would drop the other variable, and just use one]
e.g.

// Diagonal sum:
double matrix[5][5];
// .. stuff.
for(int i=0;i<5;i++)
  sum+=matrix[i][i];

Thanks, StuXYZ, your "tutorial" is very helpful and much appreciated! This example not only tells me about how to use for loops with two indices, but also understand better about assignment and memory location!

Thanks for your time!

This article has been dead for over six months. Start a new discussion instead.