1

Why is *(multi + row) producing a pointer address instead of a value? Im confused but there must be a good explanation, but i dont know still.

#include <stdio.h>
#define ROWS 5
#define COLS 10
int multi[ROWS][COLS];
int main(void)
{
    int row, col;
    for (row = 0; row < ROWS; row++)
    {
        for (col = 0; col < COLS; col++)
        {
            multi[row][col] = row*col;
        }

    }
    for (row = 0; row < ROWS; row++)
    {
        for (col = 0; col < COLS; col++)
        {
            printf("\n%d ",multi[row][col]);
            printf("%d ",*(*(multi + row) + col));
        }
    }
    return 0;
}
Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
kandelvijaya
  • 1,545
  • 12
  • 20
  • Look at this question, [Two Dimensional Array Implementation Using Double Pointer](http://stackoverflow.com/questions/13974001/two-dimensional-array-implementation-using-double-pointer/13974117#13974117) Notice the figure in MOHAMED's answer – Grijesh Chauhan Jun 10 '13 at 11:25

5 Answers5

7

It doesn't. multi is a two-dimensional array, so dereferencing the pointer which it decays into when you perform pointer arithmetic on it results in an array (which is COLS elements wide).

Steps:

  1. int multi[ROWS][COLS]; - here multi is a two-dimensional array.

  2. multi + row - here multi decayed into a pointer of type int (*)[COLS]

  3. *(multi + row) - this is equivalent with multi[row], i. e. the type of this expression is int[COLS].

4

Because multi is a 2D array which evaluates to a block pointer.

*(*(multi + row));

should get you a value.

*(multi + row);

evaluates to a pointer to the row whose index is determined by 'row'

Update:

A block pointer still contains an address like other pointers, but it's arithmetic operates on blocks instead of single elements e.g. a pointer to first row of an array. If you increment it, it would skip one row of array (rather than one element as in case of a normal pointer).

fkl
  • 5,412
  • 4
  • 28
  • 68
  • I was adding explaination of block pointer. Why are people so fast with downvotes? Just added that. Please be patient in your assessment. – fkl Jun 10 '13 at 11:17
  • As far as the C standard is concerned, such a data type is called a "pointer to array [of N elements]" instead. –  Jun 10 '13 at 11:19
  • I am pretty certain the terms are interchangeable. I learned it in my first programming course in C, some 11 years ago. Let me look for a reference and will add that here. Thanks. – fkl Jun 10 '13 at 11:22
2

multi has a type of the form "array of arrays", so in most contexts, it decays to a type of the form "pointer to array". After adding row, it still has "pointer to array" type, but possibly points to an array other than the first array (first row) in multi.

Now, applying the * operator to "pointer to array" results in an array type, which again decays to a pointer to its initial element. This pointer has type "pointer to int".

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
1

Because it's a two-dimensional array, you have two levels of indirection to go through before getting to the value.

Crowman
  • 25,242
  • 5
  • 48
  • 56
1

multi is an array of integer array i.e int (multi[rows])[cols].

multi can decay to a pointer to integer array. so multi can decay to int (*multi)[cols].

so when you do multi+rows you are doing this essentially

sizeof(int [cols]) + sizeof(int[cols])...`row` times 

and when you dereference it you get a element of type array of ints i.e the address of the first element of the integer array that you got in multi+row. now add offset to this dereferenced pointer and then dereference again, you will get the element i.e

*(multi+row) /*call this x*/-->gives an element of type int[] and int[] can decay to int*.
*(x+cols) --> gives you the element.
Koushik Shetty
  • 2,146
  • 4
  • 20
  • 31
  • Thanks!! is there a way to reverse engineer it? I mean to say: how do you declare a double pointer and end up initialing all the array elements? – kandelvijaya Jun 10 '13 at 12:27
  • 1
    if you use double pointers then too its the same way. declare like this `int **multi;` and use it as i showed above.but this has 2 immediate issues. 1) you need to have a memory allocated already, otherwise UB. 2) you need to do all the book keeping on where you are indexing. dont use double pointers if you can create 2-D array. – Koushik Shetty Jun 10 '13 at 12:32
  • Thank you!! Sure this will help. – kandelvijaya Jun 10 '13 at 17:18