0

I can use pointer for one-dimension array for function, but I don't know use the same technique for two-dimension array.

Here is my example code :

     int main(){
          int b[10]; //initialize b
          Print(b);
          int a[10][10]; //initialize a
          Print2(a);
        }

        void Print(int*b){  
           for(int i=0; i<10; i++)
              printf("%d\n",*(b+i));
        }

    // I want to use same technique here
    // but i have met error 

        void Print2(int*a){
           for(int i=0; i<10; i++)
              for(int j=0; j<10; j++)
                  printf("%d\n",*(*(a+i)+j));  // error at this line
        }

Please help me how to use same technique of one-dimension array for two-dimension array.

Thanks :)

hqt
  • 29,632
  • 51
  • 171
  • 250

5 Answers5

1

destroy the inner * and multiply i with 10 then add j

 printf("%d\n",*((a+i*10)+j));

because going "downwards" in a 2d matrix, you go through dimension-1(10 in this example) elements.

for 3d:

 printf("%d\n",*(a+i*100+j*10+k));

for N-dimensions:

  *(a+i*(size of i-dimension)+j*(size of j dim)+......+last index)
huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97
1

I've found this paste extremely useful, called "array decay". Check the comments above each example line for the type.

http://ideone.com/1PyNC

dizzylizzy
  • 13
  • 2
1

b is an array of ints, so its first element is an int. When b decays to a pointer to its first element, the result is therefore an int* (and that's what your Print function accepts).

a is an array of arrays, so its first element is an array. When a decays to a pointer to its first element, the result is therefore a pointer-to-array-of-10-ints:

void Print2(int (*a)[10] ){    // pointer-to-array type
    for(int i=0; i<10; i++)
        for(int j=0; j<10; j++)
            printf("%d\n",a[i][j]);
}

Multi-dimensional arrays only get you so far in C, because when you pass them around only the first dimension is variable. The remaining dimensions need to be known at compile-time because they're part of the pointer type. If you need something that's variable in multiple dimensions, you can "flatten" it as in tuğrul büyükışık's answer and use a 1-dimensional array.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
1

The thing is, an array decays to a pointer, but a two-dimendional array decays to a pointer to an array of specific size.

#include "stdio.h"

void print(int *arr);
void print2D(int (*arr)[]);

int main() {
    int data[5] = {1, 2, 3, 4, 5};
    print(data);

    int data2D[5][5];
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            data2D[i][j] = (i + 1) * 10 + (j + 1);
        }
    }
    print2D(data2D);
}

void print(int *arr) {  
    for (int i = 0; i < 5; i++) {
        printf("%d\n", arr[i]);
    }
}

void print2D(int (*arr)[5]) {  
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            printf("%d\n", arr[i][j]);
        }
    }
}

Here, as you can see, I declared array in the two-dimensional function as a pointer to arrays of 5 elements. Now when I increment i, the compiler knows that I want to skip five elements. You can run this example at Ideone.

You can do it manually, of course. In this case you will have to calculate the address yourself. In this case, the function will look like this:

void print2D(int *arr) {  
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            printf("%d\n", *(arr + (i * 5) + j));
        }
    }
}

You will have to call it this way:

print2D(data2D[0]);

The second example on Ideone.

Malcolm
  • 41,014
  • 11
  • 68
  • 91
  • It's not clear to me whether or not the last example is valid. I think it probably is, but James Kanze (C++ guru) thinks that it probably isn't. IIRC his grounds were that it violates strict aliasing. Also it uses a pointer to the first element of `data2D[0]` in a pointer arithmetic expression that exceeds the bounds of `data2D[0]`. – Steve Jessop Jul 20 '12 at 09:02
  • @SteveJessop If you want to be absoultely correct about the last example, use `&data2D[0][0]`. That's the pure address of the first element. As for what example to choose, I agree that it is best to use the first one, that is why it is the first example. Pointer arithmetic should be used only when it is really needed. – Malcolm Jul 20 '12 at 09:17
  • @SteveJessop Do you have a link to James' post on that issue. It surprises me, since most would agree with you that "data2D[0]" is correct (or so most have been taught, since it returns an array of integers and like any array, it decays into a pointer to its first element, an "int") – Larry Jul 20 '12 at 12:26
  • @Larry I think he meant that you're given a pointer to an array of five elements, so you are not supposed to go outside its boundaries. But I agree with you. The array boundaries are not declared anywhere like in the first example, the function doesn't know anything about the array anyway. The function only has to get the proper address, doesn't matter which way. And the calling code ensures that the function operates within allocated memory. – Malcolm Jul 20 '12 at 12:46
  • @Malcom Ok, I see now. I didn't make the connection at first but it would still be (very) surprising to discover it's not sound. While dirty IMHO (for real-world code), it should nevertheless work based on everything I've ever read. The op can consult my own post here if they want to know how to pass the array's size in: http://stackoverflow.com/questions/9672731/manipulating-multidimensional-arrays-with-functions-in-c/9677552#9677552 – Larry Jul 20 '12 at 13:33
1
        #include <stdio.h>

        void Print(int*b)
        {
        int i;
           for(i=0; i<10; i++)
              printf("%d\n",*(b+i));
        }


        void Print2(int*a)
        {
           int i,j;
           for( i=0; i<10; i++)
           {
              printf("\n");
              for(j=0; j<10; j++)
                  printf("%d\t",*(a+(i*10)+j));  // Modification done here.
           }
        }

        int main()
        {
          int b[10]; //initialize b
          Print(b);
          int a[10][10] = {}; //initialize a 0
          Print2((int*)a);
          return 0;
        }

I have modified the Print2().

Add the (Size of 1D Array * Which 1D array to be accessed(i)) + particular element in 1D Array(j) to Base Address of Array.

Jeyaram
  • 9,158
  • 7
  • 41
  • 63