Thread: How to pass pointer of 2d array to function

  1. #1
    Registered User Alpo's Avatar
    Join Date
    Apr 2014
    Posts
    877

    How to pass pointer of 2d array to function

    Hello,

    I am wanting to pass a a pair of 2d array pointers into a function that will copy one into the other. The way I'm trying is to do it like this:

    Code:
    void copy(char *copyto, char *copyfrom)
    {
        int row, col;
    
        char (*p1)[10];
        char (*p2)[10];
    
        p1=copyfrom;
        p2=copyto;
    
        for(row=0; row<ROWSIZE; ++row){
            for(col=0; col<COLSIZE; ++col){
                *(*(p2+row)+col)=*(*(p1+row)+col);
            }
        }
    }
    This compiles, and gives correct output, but also gives me the warning of: warning:"assignment from incompatible pointer type".

    The pointers are being passed to the function like this (full program):

    Code:
    #include<stdio.h>
    #define ROWSIZE  2
    #define COLSIZE 10
    
    void copy(char *copyto, char *copyfrom);
    
    main()
    {
        char array1[ROWSIZE][COLSIZE]={{'a','b','c','d','e','f','g','h','i','j'},
                                                     {'1','2','3','4','5','6','7','8','9','\0'}};
        char array2[ROWSIZE][COLSIZE];
    
        int row, col;
    
        char *ptr1;
        char *ptr2;
        ptr1=array1;
        ptr2=array2;
    
        copy(ptr2, ptr1);
    
        printf("%s", array2);
    
        return 0;
    }
    
    void copy(char *copyto, char *copyfrom)
    {
        int row, col;
    
        char (*p1)[COLSIZE];
        char (*p2)[COLSIZE];
        p1=copyfrom;
        p2=copyto;
    
        for(row=0; row<ROWSIZE; ++row){
            for(col=0; col<COLSIZE; ++col)
                *(*(p2+row)+col)=*(*(p1+row)+col);
        }
    }
    My question is, what is the correct and proper way to pass a pointer of this kind to a function? char (*p1)[COLSIZE];

    Thanks, Alpo.

    Edit: Can't fix the way the initialization of array1 looks in main, my apologies.
    Last edited by Alpo; 04-24-2014 at 11:52 AM.

  2. #2
    Registered User Alpo's Avatar
    Join Date
    Apr 2014
    Posts
    877
    Ok, I think I figured it out with some help from a faq (Question 6.12). I'm now getting no warnings. I will erase the thread if anyone wants, it just took a while to find a reference for this specific thing. Solution below.

    Edit: I don't actually know if I can erase the thread :{|

    Edit2: Fixed code, and update about warnings. Under debug mode, I get the warning "return from incompatible pointer type". Output is fine though.

    Code:
    #include<stdio.h>
    #define ROWSIZE  2
    #define COLSIZE 10
    
    char *copy(char (*ptr)[COLSIZE], char (*ptr2)[COLSIZE]);
    
    int main(void)
    {
        char array1[ROWSIZE][COLSIZE]={{'a','b','c','d','e','f','g','h','i','j'},
                                      {'1','2','3','4','5','6','7','8','9','\0'}};
        char array2[ROWSIZE][COLSIZE];
    
        char (*ptr1)[COLSIZE];
        char (*ptr2)[COLSIZE];
        ptr1=array1;
        ptr2=array2;
    
        copy(ptr2, ptr1);
    
        printf("%s", *ptr2);
    
        return 0;
    }
    
    char *copy(char (*copyto)[COLSIZE], char (*copyfrom)[COLSIZE])
    {
        int row, col;
    
        for(row=0; row<ROWSIZE; ++row){
            for(col=0; col<COLSIZE; ++col)
                *(*(copyto+row)+col)=*(*(copyfrom+row)+col);
        }
        return copyto;
    }
    Last edited by Alpo; 04-24-2014 at 01:53 PM.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Alpo
    Edit2: Fixed code, and update about warnings. Under debug mode, I get the warning "return from incompatible pointer type". Output is fine though.
    Perhaps under your debug configuration, warnings are set to a higher level (which they should be). The reason for this warning is that you return copyto from your copy function, but your copy function is declared as returning a pointer to char, whereas copyto is a pointer to an array of COLSIZE char. It would probably be reasonable to just change the return type to void and not return anything since you did not use the return value anyway.

    By the way, instead of writing the ugly, obfuscated and error-prone long line:
    Code:
    *(*(copyto+row)+col)=*(*(copyfrom+row)+col);
    Write:
    Code:
    copyto[row][col] = copyfrom[row][col];
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Feb 2014
    Location
    NY
    Posts
    56
    Code last posted doesn't compile or run for me.

    Code:
    //return copyto; //changed to
    return *copyto;
    Now compiles and runs with no errors.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by 3DT
    Now compiles and runs with no errors.
    That does not mean that it is logically correct.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Feb 2014
    Location
    NY
    Posts
    56
    Quote Originally Posted by laserlight View Post
    It would probably be reasonable to just change the return type to void and not return anything since you did not use the return value anyway.
    Code:
    #include<stdio.h>#define ROWSIZE  2
    #define COLSIZE 10
     
    void copy(char (*ptr)[COLSIZE], char (*ptr2)[COLSIZE]);
     
    int main(void)
    {
        char array1[ROWSIZE][COLSIZE]={{'a','b','c','d','e','f','g','h','i','j'},
                                      {'1','2','3','4','5','6','7','8','9','\0'}};
        char array2[ROWSIZE][COLSIZE];
    
    
        char (*ptr1)[COLSIZE];
        char (*ptr2)[COLSIZE];
        ptr1=array1;
        ptr2=array2;
     
        copy(ptr2, ptr1);
     
        printf("%s", *ptr2);
     
        return 0;
    }
     
    void copy(char (*copyto)[COLSIZE], char (*copyfrom)[COLSIZE])
    {
        int row, col;
     
        for(row=0; row<ROWSIZE; ++row){
            for(col=0; col<COLSIZE; ++col)
                copyto[row][col] = copyfrom[row][col];
        }
        return;
    }

  7. #7
    Registered User
    Join Date
    Feb 2014
    Location
    NY
    Posts
    56
    Quote Originally Posted by laserlight View Post
    That does not mean that it is logically correct.
    What else is wrong with it?

    My debugger returned this but I have no idea what it means.
    Code:
    Thread 1740 ended with 0
    Process 152C ended with 0

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by 3DT
    What else is wrong with it?
    What did Alpo intend by having a return value for the copy function? Besides silencing the compile error/warning, why did you return *copyto?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User Alpo's Avatar
    Join Date
    Apr 2014
    Posts
    877
    @Laserlight- I was actually going to put the function directly into the printf, but ended up not doing so. I realize the pointer arithmetic is harder to read, but this was all part of educating myself (trying to anyway), that's also why I passed a pointer rather than just the array, just to learn .

    I thought the reason the pointers were incompatible was because it was a pointer to an array of multiple chars (thanks Laserlight), but I'm still not sure how to correctly pass just the first address of the array the pointer is pointing at. What if I need the function to pass a pointer to the first address of the array, is that possible using the: (*ptr) [COLUMN] approach that is in the second code? Edit: I mean like passing it to a function that is not in the scope of the original declaration of the array.

    My first attempt was trying to get around this by passing just the first address, and then modifying it in the function to work with the 2nd dimension.

    Code:
    void copy(char *copyto, char *copyfrom)
    {
        int row, col;
     
        char (*p1)[COLSIZE];
        char (*p2)[COLSIZE];
        p1=copyfrom;
        p2=copyto;
    
    This ended up compiling, but with a lot of errors.

    @3DT- I'm not sure, my compiler is set to give max warnings, and I never saw that. I only just started using the debugger though (code::blocks). Maybe it means you need a new shirt :P ?

    Thanks everyone for responding, it means a lot.
    Last edited by Alpo; 04-25-2014 at 12:13 AM. Reason: clarification

  10. #10
    Registered User
    Join Date
    Feb 2014
    Location
    NY
    Posts
    56
    @Alpo
    Isn't an array already a bunch of pointers? array, array[0], or array1[0][0] would be a pointer to the first element.

    Code:
    #include<stdio.h>
    int main(void){
        char array1[2][5]={{'\0'},{'\0'}};
        printf("The address of array1 is %x\n",&array1);
        printf("The address of array1 is %x\n",&array1[0]);
        printf("The address of array1 is %x\n",&array1[0][0]);
        return 0;
    }
    Quote Originally Posted by laserlight View Post
    What did Alpo intend by having a return value for the copy function? Besides silencing the compile error/warning, why did you return *copyto?
    I'm not really sure what he intended with the return value. To be useful shouldn't a variable be set to the calling function? like a=myfunction(b);? The pointer will change the value in memory so there is no need to return anything.

    The only reason was to silence the error.
    Last edited by 3DT; 04-25-2014 at 06:13 AM.

  11. #11
    Registered User
    Join Date
    Feb 2014
    Location
    NY
    Posts
    56
    I'm just curious what is the correct output? You leave no space for the terminating null character in your array. When you give enough space it only reads the first column. With out enough space to hold the null character it keeps reading to the next block of memory until the null character.

    Code:
    #include<stdio.h>
    #define ROWSIZE  2
    #define COLSIZE 11
    void copy(char (*ptr)[COLSIZE], char (*ptr2)[COLSIZE]);
    void CPY(char a[][COLSIZE], char b[][COLSIZE]);
    int main(void)
    {
        char array1[ROWSIZE][COLSIZE]={{'a','b','c','d','e','f','g','h','i','j'},
                                      {'1','2','3','4','5','6','7','8','9','\0'}};
        char array2[ROWSIZE][COLSIZE]={{'\0'},{'\0'}};
    
        char (*ptr1)[COLSIZE];
        char (*ptr2)[COLSIZE];
        ptr1=array1;
        ptr2=array2;
     
        copy(ptr2, ptr1);
        printf("%s\n", *ptr2);
    
        array2[0][0]='\0';
        printf("%s\n", *array2);
        
        CPY(array1, array2);
        printf("%s\n", *array2);
     
        return 0;
    }
    void copy(char (*copyto)[COLSIZE], char (*copyfrom)[COLSIZE])
    {
        int row, col;
     
        for(row=0; row<ROWSIZE; ++row){
            for(col=0; col<COLSIZE; ++col)
                copyto[row][col] = copyfrom[row][col];
        }
        return;
    }
    void CPY(char a[][COLSIZE], char b[][COLSIZE]){
        int row, col;
     
        for(row=0; row<ROWSIZE; ++row){
            for(col=0; col<COLSIZE; ++col)
                *(*(b+row)+col)=*(*(a+row)+col);
        }
        return;
    }
    ROWSIZE 11
    Code:
    abcdefghij
    
    
    abcdefghij
    ROWSIZE 10
    Code:
    abcdefghij123456789
    
    
    abcdefghij123456789
    Last edited by 3DT; 04-25-2014 at 07:22 AM. Reason: code formating

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Alpo
    that's also why I passed a pointer rather than just the array
    You will be passing a pointer either way. It is just a matter of syntax.

    Quote Originally Posted by Alpo
    I'm still not sure how to correctly pass just the first address of the array the pointer is pointing at.
    The pointer is only pointing to one array. That array happens to be the first array in an array of arrays. So, what does "first address of the array" mean?

    Quote Originally Posted by Alpo
    What if I need the function to pass a pointer to the first address of the array, is that possible using the: (*ptr) [COLUMN] approach that is in the second code? Edit: I mean like passing it to a function that is not in the scope of the original declaration of the array.
    Consider:
    Code:
    #include<stdio.h>
    
    #define ROWSIZE  2
    #define COLSIZE 10
    
    void foo(char (*y)[COLSIZE]);
    void bar(char (*z)[COLSIZE]);
    
    int main(void)
    {
        char x[ROWSIZE][COLSIZE] = {{0}};
        foo(x);
    
        return 0;
    }
    
    void foo(char (*y)[COLSIZE])
    {
        bar(y);
    }
    
    void bar(char (*z)[COLSIZE])
    {
        z[0][0] = 1;
    }
    Quote Originally Posted by 3DT
    Isn't an array already a bunch of pointers? array, array[0], or array1[0][0] would be a pointer to the first element.
    No, an array is not a pointer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User Alpo's Avatar
    Join Date
    Apr 2014
    Posts
    877
    Thanks Laserlight & 3DT, I'm still pretty new but think I'm catching on, you don't have to return because an array acts like a pointer to it's first element anywhere it's scope is.

    By first address I just meant the first element (x[0][0]). I was returning was because I had planned to put the copy() directly into the printf(), don't know why I was going to do it that way.

    When first learning about functions I had the impression that all they did was return a value, I know that's way off now, but sometimes still do a thing based on that first impression. One of the perils of self teaching is that you pick up bad habits from initial confusion and have to modify your way of thinking about a thing later.

    Edit: @3DT- I didn't put a terminating null character in the first row because I read that 2d arrays have contiguous memory between rows (it is there at the end of the 2nd row). Once I had the copying working, I was going to switch the condition of the nested for loop to be *(*(copyfrom+row)+col) !='\0' , to see what would happen. (I just tried it and it doesn't work that way, it seems to overflow the array).


    Just thought for people who look this question up on here I would link this tutorial on pointers. It's huge, informative, and beginner friendly -

    A Tutorial on Pointers and Arrays in C
    Last edited by Alpo; 04-25-2014 at 11:09 AM.

  14. #14
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    If you actually wanted a pointer to a 2d array (matrix):

    Code:
    /* ... */
        char (*ptr2d)[][COLSIZE] = array2d;
    /* example usage */
        (*ptr2d)[j][i] = array2d[j][i];
    Note that the first dimension (ROWSIZE) does not need to be specified for a 2d array, but if it is specified, then it could be a pointer to the first matrix of a 3d array.

    Code:
    /* ... */
        char tensor[MATRIXSIZE][ROWSIZE][COLSIZE];
    /* ... */
        char (*ptrtofirstmatrix)[ROWSIZE][COLSIZE] = tensor;
    /* example usage */
        ptrtofirstmatrix[k][j][i] = tensor[k][j][i];
    What you currently have is a pointer to a 1d array of size COLSIZE, which in this case is a pointer to the first row of a 2d array.
    Last edited by rcgldr; 04-25-2014 at 03:57 PM.

  15. #15
    Registered User
    Join Date
    Feb 2014
    Location
    NY
    Posts
    56
    Quote Originally Posted by laserlight View Post
    No, an array is not a pointer.
    I was taught that the array name is a pointer to the array. If its not then why can we access an array using a pointer of arrays name?

    Code:
    #include<stdio.h>
    int main(void){
    
    
        int array[5][5]={{'A','G','Y','\0'},{'B','X','Z','\0'},{'C','B','J','\0'},{'D','O','F','\0'}};
         /*array[0] points to memory address of array[0][0]
        array[1] points to memory address of array[1][0]
        array[2] points to memory address of array[2][0]
        array[3] points to memory address of array[3][0]*/
    
    
        printf("The value of array[0][0] is %c\n",*(array[0]));
        printf("The value of array[0][1] is %c\n",*(array[0]+1));
        printf("The value of array[0][2] is %c\n",*(array[0]+2));
        printf("The value of array[1][0] is %c\n",*array[1]);
        printf("The value of array[1][1] is %c\n",*(array[1]+1));
        printf("The value of array[1][2] is %c\n",*(array[1]+2));
        printf("The value of array[2][0] is %c\n",*array[2]);
        printf("The value of array[2][1] is %c\n",*(array[2]+1));
        printf("The value of array[2][2] is %c\n",*(array[2]+2));
        printf("The value of array[3][0] is %c\n",*array[3]);
        printf("The value of array[3][1] is %c\n",*(array[3]+1));
        printf("The value of array[3][2] is %c\n",*(array[3]+2));
     return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pass pointer to function
    By markucd in forum C++ Programming
    Replies: 3
    Last Post: 01-07-2006, 01:18 PM
  2. pass the pointer of a two dimension array to a function
    By SoFarAway in forum C Programming
    Replies: 8
    Last Post: 04-13-2005, 05:43 AM
  3. Replies: 6
    Last Post: 11-29-2004, 08:50 AM
  4. A pointer to a character pointer array... can't pass
    By Lynux-Penguin in forum C Programming
    Replies: 9
    Last Post: 10-12-2003, 10:53 PM
  5. Replies: 3
    Last Post: 04-02-2002, 01:39 PM

Tags for this Thread