5

I am trying to print a 2D matrix with using [], instead I want to use * like a pointer.
So with a 1 D array I'd do: *(arr+i) for example. What's the syntax used to replace in matrix[][] ?

Here's the code:

for (i = 0; i < size; i++)
{
    for (j = 0; j < (size * 2); j++)
    {
        printf(" %5d", matrix[i][j]);
    }
    printf("\n");
}

P.S, I did try several things like:

*(matrix+i+j);
*(matrix+i)+*(matrix+j);

Of course none of that worked.

Thank you for your help and time!

haccks
  • 104,019
  • 25
  • 176
  • 264
Isan Rivkin
  • 177
  • 1
  • 15

3 Answers3

6

Use the * two times. Each of * will basically replace one []:

*(*(matrix+i)+j)
Zbynek Vyskovsky - kvr000
  • 18,186
  • 3
  • 35
  • 43
  • 1
    @Pixelchemist No it's not. It works due to array decaying into pointer. – user694733 Feb 10 '16 at 10:58
  • It's correct because the array *does not* decay into a pointer. – alain Feb 10 '16 at 10:59
  • 2
    @user694733 Why would array decay to pointer here ? ( _if not previously declared a pointer_). – ameyCU Feb 10 '16 at 11:02
  • 1
    @ameyCU user694733 is correct. Rhetorical question: how can you have pointer arithmetic without pointers? – 2501 Feb 10 '16 at 11:04
  • If you have a pointer, Paul Ogilvie's addressing works, but *only if* you have a pointer. This on the other hand works *only* when the array is not a pointer. – alain Feb 10 '16 at 11:05
  • 1
    Array `matrix` with type `int[][]` decays to pointer `&matrix[0]` with type `int(*)[]` (I hope I wrote that right) before `+i` is performed. – user694733 Feb 10 '16 at 11:05
  • 1
    @2501 That's fine , writing `matrix` will point to base element but that's not decaying (_if I am not wrong_). – ameyCU Feb 10 '16 at 11:08
  • @ameyCU; It's called decaying. `*(*(matrix+i)+j)` an expression and in this expression `matrix` decay to pointer to it's first element which will again decay to its first element (an `int`). – haccks Feb 10 '16 at 11:10
  • @alain : this will work in any case as this dereferencing holds the type of the expression. So after applying the first `+` the expression type will become `int (*)[15]`, after another the type will be `int *`. Similarly to pointer of pointers - it will be `int **` and after another `+` will become `int *` again. – Zbynek Vyskovsky - kvr000 Feb 10 '16 at 11:11
  • @hacks I don't mean to be stubborn but your last comment come to me as dereferencing and decaying as same thing . – ameyCU Feb 10 '16 at 11:13
  • 2
    N1570 chapter 6.5.2.1 has example of subscripting array `int x[3][5];` with sentence: *"...In the expression `x[i]`, which is equivalent to `(*((x)+(i)))`, `x` is first converted to a pointer to the initial array of five ints. ..."* – user694733 Feb 10 '16 at 11:16
  • 1
    @ZbynekVyskovsky-kvr000 What I meant is it doesn't work with `(int*)matrix` – alain Feb 10 '16 at 11:20
  • 1
    @ameyCU; OK. Let it be clear. The expression `*(*(matrix+i)+j)` is perfectly valid whether `matrix` is an *array of arrays* of *pointer to pointer*. In case of 2D array, in the expression `*(matrix+i)`, `matrix` will decay to pointer to `matrix[0]`. So, `*(matrix+i)` is equivalent to `*(&matrix[0] + i)`. `&matrix[0] + i` will give the address of `matrix[i]`. Now `(matrix+i)` is equivalent to `&matrix[i]`. Dereferencing `&matrix[i]` will result in array `matrix[i]`. Now `matrix[i]` is an array itself, so it will decay to pointer to `matrix[i][0]`. `&matrix[i][0] + j` will give..... – haccks Feb 10 '16 at 11:24
  • @hacks This clears it up between the terms (_my confusion between them_) . Thanks :-) – ameyCU Feb 10 '16 at 11:33
  • @Puck; No, it will not work. `*(matrix+i*size+j)` will launch you somewhere in the space. – haccks Feb 10 '16 at 11:40
  • @hacks: tried it and noticed it. But why? I fought 2D matrix in C was simply a bigger 1D matrix, as explained here: [link](http://stackoverflow.com/questions/2565039/how-are-multi-dimensional-arrays-formatted-in-memory?lq=1). And I am quiet sure I used trick like that during courses on C... – Puck Feb 10 '16 at 14:25
  • @Puck `*((int*)matrix + i*size + j)` should work. The problem is that `matrix` is a pointer to a 1D-array. – alain Feb 10 '16 at 15:37
2

You can try this-

*(*(matrix+i)+j)  //reduce level of indirection by using *  
ameyCU
  • 16,489
  • 2
  • 26
  • 41
0

This may depend on how matrix was allocated or passed to a function.

int A[10][15];

This uses a contiguous block of memory. To address the elements without using array notation use:

        A +(i*15)+j    // user694733 showed this is wrong
((int *)A)+(i*15)+j    // this is horribly ugly but is correct

Note the 15, as each row consists of 15 elements. Better solutions are presented in other answers here.

In the following:

int *A[10];

A is an array of 10 pointers to ints. Assuming each array element has been allocated using malloc, you address the elements without using array notation as:

*(A+i) + j;

that is, you take A, then take the ith element, dereference that and add j as the second index.

--EDIT--

And to be complete:

int foo(int *p)

here a function just receives a pointer to zero or more ints. The pointer points to a contiguous, linear block of memory into which you can place an n-dimensional array. How many dimensions there are and the upper bound of each dimension the function can only know through parameters or global variables.

To address the cells of the n-dimensional array, the programmer must calculate the addresses him/herself, using the above notation.

int foo3(int *m, int dim2, int dim3, int i,  int j, int k)
{
    int *cell = m + i*dim3*dim2 + j*dim2 + k;
    return *cell;
}
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • 1
    Using `A+(i*15)+j` is error prone and unnecessary. It's only needed if you allocate 2D as 1D array. – user694733 Feb 10 '16 at 10:57
  • @user694733, all arrays of the form `int A[10][15]` are contiguous in memory. That has nothing to do with "allocating a 2D as 1D array." I can treat any contiguous block of memory as an n-dimensional array. It is just to show the OP how to do it. It is not nice, but that's what he wants to learn. – Paul Ogilvie Feb 10 '16 at 11:06
  • `*(*(matrix+i)+j)` does it without needing to specify the size explicitly. – user694733 Feb 10 '16 at 11:09
  • @user694733, I'd like to see this when the array is of variable size and passed as a pointer such as `foo(int *A, int size1)`. Without knowing the dimensions at compile time, C can't solve it and the addressing must be as `A+(i*size1)+j` – Paul Ogilvie Feb 10 '16 at 11:12
  • By variable size I guess you mean allocated with `malloc`? If so, then either it's array of pointers to arrays (also known as jagged arrays) or 1D array used as 2D array. For former you can do the `*(*(A+i)+j)`, and for latter you must do `A+(i*N)+j`. But neither it's not the same as *"true"* 2D array, defined as `int A[10][15]`. – user694733 Feb 10 '16 at 11:22
  • 1
    Your "true" 2D array, defined as int A[10][15]" is just a contiguous block of memory and the compiler uses the `A+(i*N)+j` calculation. – Paul Ogilvie Feb 10 '16 at 12:19
  • 2
    Perhaps it does so *internally*. But if you do it manually, then types are all wrong, unless you add casting. For variable `int m[2][2];` accessing last element `m[1][1]` using syntax `m+(i*size)+j`, now `m+(1*2)+1`, will expand to `(char*)&m[0] + sizeof(int[2]) * ((1*2)+1)`, which is **out of array bounds**. [Example on Ideone](http://ideone.com/47IdI7). – user694733 Feb 10 '16 at 13:47
  • @user694733, I see... The type is `int[2]` where my premises was the type was just `int`. – Paul Ogilvie Feb 10 '16 at 18:47