0
#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?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 3
    `ptr` is always less than `ptr+19`, at least until the pointer runs off the end of the address space and wraps around, but it is likely to be pointing to invalid memory before that happens. – Ian Abbott Jul 07 '21 at 11:35
  • 2
    "Does not work" is not a useful statement. What ***does*** it do? – Andrew Henle Jul 07 '21 at 11:35
  • Apart from the obvious bug `ptr < ptr+19` you aren't allowed to de-reference arrays in this manner. You go out of bounds in the array access and it's undefined behavior. The compiler is allowed to go nuts and generate strange code or a crashing program. – Lundin Jul 07 '21 at 14:26

3 Answers3

2

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);
    }
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • wait a minute the ptr+19 adds 19 to the pointer each time?! – programmer29874 Jul 07 '21 at 11:38
  • @programmer29874 Yes... or maybe no because the condition `ptr < ptr+19` may be turned into an unconditional "true" by the optimizer. – MikeCAT Jul 07 '21 at 11:40
  • wow i did not realize that Mike thanks a lot, you seem to be pro at C could you recommend me something to get better at C? maybe a book or some materials ;P – programmer29874 Jul 07 '21 at 11:41
  • 2
    @programmer29874 Try it with `int`: `for (int x = 0; x < x + 19; x++) printf("%d ", x);`. How many iterations do you think it should do? – Ian Abbott Jul 07 '21 at 11:44
  • i will try that thanks, also guys what is this type of behavior called specifically what the way the pointer still gets incremented even when its being tested in a condition like in the for loop – programmer29874 Jul 07 '21 at 11:46
  • @programmer29874 [The Definitive C Book Guide and List](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) – Ian Abbott Jul 07 '21 at 11:47
  • 1
    @programmer29874: this is not really a C issue. It's just that the mathematical expression `x < x + y`, where `0 < y` always holds true, regardless of if it's part of a program or just some manually executed arithmetic. The conditional part of a loop is evaluated *whole* on each iteration. The compiler is not a magical beast that sees an expression like `a < b` and *thinks* "oh, I'll have to reevaluate `b` and only `b` each time". – datenwolf Jul 07 '21 at 11:47
  • @programmer29874 You seem to be confused. `ptr`'s value does not get changed by `ptr < ptr+19`. `ptr` and `ptr+19` are two different pointer values, but the first is always less than the second (at least until it goes wrong). – Ian Abbott Jul 07 '21 at 11:49
  • but when the compiler sees ```ptr+19``` doesnt it add 19 to ptr then compare it to ```ptr``` – programmer29874 Jul 07 '21 at 11:53
0

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
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • i have one question does the condition ```ptr < ptr+19``` add ```19``` to ```ptr``` each time its evaluated? – programmer29874 Jul 07 '21 at 11:58
  • @programmer29874 ptr is incremented in the third expression of the for loop ptr++. In the second expression (condition) of the for loop there are compared two expressions ptr and ptr + 19. – Vlad from Moscow Jul 07 '21 at 12:03
0

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;
    
}
Edgen
  • 69
  • 7