How can I use 2 or more dimension array as parameter

Discussion in 'Mac Programming' started by DeathscytheSeph, Dec 4, 2008.

  1. DeathscytheSeph macrumors newbie

    Joined:
    Jul 9, 2007
    #1
    I am new to Objective-C and Cocoa. and now I have a problem.
    I want to send 2 dimension array to function but it cannot compile the error is "array type has incomplete element type" Please help me

    This is my Interface
    + (void) reValueInArray: (int[][] ) labelValue replaceValue: (int) oldValue withValue: (int) newValue;

    and one more question
    How can i get length of array
    1. array that declare as array at first (int a[5] for example)
    2. array that declare as pointer at first (int a* for example)

    Thank you Very much
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    For your edification, this is all C, Cocoa isn't involved.

    So you have a few options:
    1) You have an array of int * instead of a two dimensional array, and you allocate space for each "dimension". This could be rectangular, or jagged, depending on your needs. You'd then pass an int ** to your method. You can still access the elements using [x][y]. However, you should probably also pass an array with the widths of each row, so you can safely access these elements.

    2) You have an int [][], that is one big chunk of memory. In this case you need to define all but the first dimension, so the offsets can be properly calculated. For example:
    Code:
    int myArr[5][6];
    myFunc(myArr);
    
    void myFunc(int myArg[][6]) {
    ...
    }
    When you use the first dimension, the compiler knows how to do the math to find the offset in your array.

    3) I came up with a few other options, but neither was too elegant. Both involved passing your dimensions as arguments, and one used the gcc extension to declare a variable shaped array using these arguments, then memcpy'ing over the argument that is passed in. Then you can use [][] without issue to access the new array, but you've wasted a lot of memory. For the sake of exploration, it looks like this:
    Code:
    #include <stdio.h>
    #include <string.h>
    void myfunc(int *,int,int);
    int main(int argc, char **argv) {
      int myarr[5][6];
      myarr[1][4]=8;
      myfunc(&myarr[0][0],5,6);
    }
    
    void myfunc(int *myarg,int dim1,int dim2) {
      int test[dim1][dim2],x,y;
      memcpy((void *)test,(void *)myarg,(size_t)dim1*dim2*sizeof(int));
      for(x=0;x < dim1;x++) {
        for(y=0;y < dim2;y++) {
          printf("test[%d][%d] = %d\n",x,y,test[x][y]);
        }
      }
    }
    This is wasteful, but the code looks more elegant. I came up with another way that does not use the variable shaped array extension, but the code does not look pleasant:
    Code:
    #include <stdio.h>
    
    void myfunc(int *,int,int);
    int main(int argc, char **argv) {
      int myarr[5][6];
      myarr[1][4]=8;
      myfunc(&myarr[0][0],5,6);
    }
    
    void myfunc(int *myarg,int dim1,int dim2) {
      for(x=0;x < dim1;x++) {
        for(y=0;y < dim2;y++) {
          printf("test[%d] = %d\n",x*(dim2)+y,myarg[x*(dim2)+y]);
        }
      }
    }
    
    This is essentially doing the compilers job by calculating your own offsets (though at least you're doing it by elements and not bytes). You could, of course, make a helper function that is called elementAt and obscure this from the main sections of your code:
    Code:
    int elementAt(int *list,int dim2,int x,int y){
      return list[x*(dim2)+y];
    }
    
    This still requires you to carry around the lower dimension of the array to calculate the offset.

    As for getting the length of a C-style array, you don't. An array is just a pointer to the base of the array in memory. That's all. It's not a complex data-type that carries around the length/width/# of dimensions, etc. You can #define something in a header file that defines the length of a particular thing, so you have easy access to it, but otherwise you're out of luck. You'll just need to pass the length around with the array, or find some other solution (such as passing around a struct that has the pointer, and it's length, etc.).
    Edit: I lied, a bit. If you have an int *, for example, you are out of luck. If you are in the scope where a multidimensional array is declared, you can use sizeof to get the information:
    Code:
    #include <stdio.h>
    
    int main(int argc, char **argv) {
      int myarr[5][6];
      myarr[1][4]=8;
      printf("size: %d\t%d\t%d\n",sizeof(myarr)/sizeof(int),sizeof(myarr[0])/sizeof(int),sizeof(myarr)/sizeof(myarr[0]));
    }
    
    This ultimately raises the question of why you'd go through this kind of silliness when you have dynamic data structures at your disposal in Objective-C. Unless there's a huge performance hit, why not use an NSMutableArray of NSMutableArrays of NSNumbers? Then you do have methods to get length, etc.

    -Lee
     
  3. autorelease macrumors regular

    Joined:
    Oct 13, 2008
    Location:
    Achewood, CA
    #3
    Unless your 2-dimensional array is always the same size for every run of the program, you shouldn't be using a statically-declared C array. malloc() it or use an NSMutableArray. With a helper method similar to Lee's elementAt, you can use a one-dimensional NSMutableArray like a multi-dimensional one.
     
  4. DeathscytheSeph thread starter macrumors newbie

    Joined:
    Jul 9, 2007
    #4
    Thank you both of you. I see how it work I just forget something about C

    I fix by send it as 1 dimension array and calculate by my self T_T

    but Thank you both of you very much ^^
     

Share This Page