programmer29874
programmer29874

Reputation: 1

why does this for loop iterating over 2d array not work

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main(void)
{

    int a[4][5] =
    {
       {1,1,0,1,0},
       {0,0,0,0,0},
       {0,1,0,0,0},
       {1,0,1,1,0}
    };

    int *ptr = &a[0][0];

    for (; ptr < ptr+19; ptr++)
    {
        printf("%d ", *ptr);
    } 
  
    return 0;
    
}

Why does this code not work? as far as i know 2D arrays are stored in row major order so like this:

[1,1,0,1,0]-[0,0,0,0,0]-[0,1,0,0,0]-[1,0,1,1,0]

So if i started at &a[0][0] and incremented it by 1 each time until it has been incremented to the last element why does this not work?

Upvotes: 0

Views: 93

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

In this for loop

for (; ptr < ptr+19; ptr++)

the value of the expression ptr is always less than the value of the expression ptr + 19 (provided that there is no overflow in the last expression). Moreover the pointer ptr is incremented after each iteration of the loop.

So using this loop you will get access to memory outside the array a that results in undefined behavior.

What you need is the following for statement

for ( ; ptr < ( int * )a + sizeof( a ) / sizeof( **a ); ptr++)

Here is a demonstrative program.

#include <stdio.h>

int main(void) 
{
    int a[4][5] =
    {
       {1,1,0,1,0},
       {0,0,0,0,0},
       {0,1,0,0,0},
       {1,0,1,1,0}
    };

    for ( int *ptr = ( int * )a; ptr < ( int * )a + sizeof( a ) / sizeof( **a ); ptr++ )
    {
        printf( "%d ", *ptr );
    }
    
    putchar( '\n' );
    
    return 0;
}

The program output is

1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0

Upvotes: 0

Edgen
Edgen

Reputation: 73

Alternative approach

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{

    int a[4][5] =
    {
       {1,1,0,1,0},
       {0,0,0,0,0},
       {0,1,0,0,0},
       {1,0,1,1,0}
    };

    int len = sizeof(a)/sizeof(a[0][0]) ;
    int * ptr = &a[0][0] ;
    while(len--)
    {
        printf("%d ", *ptr++);
    }
  
    return 0;
    
}

Upvotes: 0

MikeCAT
MikeCAT

Reputation: 75062

Aside from the danger caused from accessing data with pointers for different type, the loop condition is wrong.

ptr+19 moves with ptr and the condition ptr < ptr+19 will always be true (until overflow occurs).

Your code will be better if you retain the origin pointer and use that for stop condition.

    int *ptr = &a[0][0];
    int *start_ptr = ptr;

    for (; ptr < start_ptr+19; ptr++)
    {
        printf("%d ", *ptr);
    }

Upvotes: 2

Related Questions