Pointer to a 2d array

This is a discussion on Pointer to a 2d array within the C Programming forums, part of the General Programming Boards category; I'm trying to write a program that will create and work with matrices, but im having problems with a pointer ...

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    24

    Pointer to a 2d array

    I'm trying to write a program that will create and work with matrices, but im having problems with a pointer to a 2d array.

    I created this structure in a header file:
    Code:
    typedef struct {
      int  rowdim, coldim;
      double* element;
    } matrix;
    the header file also has the function prototypes.

    Here is the file where i define the functions:
    Code:
    #include "matrix.h"
    
    matrix create_empty(int rdim, int cdim)
    {
    	matrix* new_matrix;
    	new_matrix = malloc(sizeof(matrix));
    	new_matrix -> rowdim = rdim;
    	new_matrix -> coldim = cdim;
    	new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
    	return *new_matrix;
    }
    
    matrix create_initval(int rdim, int cdim, double* values)
    {
    	int i, j;
    	matrix* new_matrix;
    	new_matrix = malloc(sizeof(matrix));
    	new_matrix -> rowdim = rdim;
    	new_matrix -> coldim = cdim;
    	new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
    	for (i=0; i<cdim; i++)
    	{
    		for(j=0; j<rdim; j++)
    			new_matrix -> element[i][j] = values[i][j];
    	{
    return *new_matrix;
    }
    
    void destroy(matrix a)
    {
    	free(&a.element);
    }
    
    void matrix_print(matrix a)
    {
    	int i, j;	
    	printf("\n");
    	for (i=0; i<a.coldim; i++)
    	{
    		for(j=0; i<a.rowdim; j++)
    		{
    			printf(" %f ", a.element[i][j]);
    		}
    	}
    }
    }
    however, there is a compile error for:
    Code:
    new_matrix -> element[i][j] = values[i][j];
    that reads: subscripted value is neither array nor pointer

    Im not sure why, because i know the program works when creating a one dimensional vector, but when its 2d, i have the problem

  2. #2
    Registered User
    Join Date
    Dec 2009
    Posts
    24
    i read something online about a double pointer being used when working with 2d arrays, but how exactly are they used?

  3. #3
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,738
    You can still do this properly without changing your design. Accesses to your matrix will look like this.

    newmatrix->element[j * rdim + i] = values[j * rdim + i];

    This works because the memory is contiguous, so item 42 is actually item (7, 6) or what have you. That's why you calculate.

  4. #4
    Registered User
    Join Date
    Dec 2009
    Posts
    24
    Alright, so i changed my code to:
    Code:
    #include "matrix.h"
    
    matrix create_empty(int rdim, int cdim)
    {
    	matrix* new_matrix;
    	new_matrix = malloc(sizeof(matrix));
    	new_matrix -> rowdim = rdim;
    	new_matrix -> coldim = cdim;
    	new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
    	return *new_matrix;
    }
    
    matrix create_initval(int rdim, int cdim, double* values)
    {
    	int i, j;
    	matrix* new_matrix;
    	new_matrix = malloc(sizeof(matrix));
    	new_matrix -> rowdim = rdim;
    	new_matrix -> coldim = cdim;
    	new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
    	for (i=0; i<cdim; i++)
    	{
    		for(j=0; j<rdim; j++)
    			new_matrix -> element[j * rdim + i] = values[j * rdim + i];
    	{
    return *new_matrix;
    }
    
    void destroy(matrix a)
    {
    	free(&a.element);
    }
    
    void matrix_print(matrix a)
    {
    	int i, j;	
    	printf("\n");
    	for (i=0; i<a.coldim; i++)
    	{
    		for(j=0; i<a.rowdim; j++)
    		{
    			printf(" %f ", a.element[j * rdim + i]);
    		}
    	}
    }
    }
    }
    I also created a test file that looks like:

    Code:
    #include "matrix.h"
    
    int main()
    {
    	double one[2][3] = {
    									     {1,2,3},
                                    {4,5,6}
    										};
    							
    
    	matrix m_one;
    	m_one = create_initval(2, 3, *one);
    	matrix_print(m_one);
    return 0;
    }
    but when i compile, i get:
    /tmp/ccgEP8z2.o: In function `main':
    test.c.text+0x7d): undefined reference to `matrix_print'
    collect2: ld returned 1 exit status

  5. #5
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    I see you used the suggestion above to use a one-dimensional array. I'd suggest not to sacrifice readability and other assumptions one might have about a (your) matrix. Matrices are inherently two-dimensional, thus you should make it two dimensional. Again, my opinion.

    As for your compile error, its probably because you need to pass both .c filenames when you compile (the matrix and test .c files).

  6. #6
    Registered User
    Join Date
    Dec 2009
    Posts
    24
    well how would i keep it as a two dimensional array? Im thinking that I'll have to use a double pointer, but dont know how to set that up.

  7. #7
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    First, are your compiler errors gone?

    Next, 2-d arrays are just "arrays of arrays". 3-d arrays are "arrays of arrays of arrays", etc.. So for a 2-d array you'd declare it as (for, say, ints)
    Code:
    int ** myArrays;
    Then this variable doesnt really point to anything useful, so you need to assign some memory to the first of it's two dimensions, say like
    Code:
    myArrays = malloc(sizeof(int*) * ROWS);
    Where "ROWS" is of course set, and you do the appropriate error checking. Recall that, since it is basically an "array of arrays", we are using the size of "int*" rather than "int". Next, for each of these rows, you allocate some memory for the corresponding column
    Code:
    myArrays[curRow] = malloc(sizeof(int) * COLS);
    Then you can read/write to the matrix, via "myArrays[rowNum][colNum]".

    Make sure that you "free" all memory you "malloc"ed. So you must iterate over the rows and free each column (freeing the second dimension). Then you can simply "free" "myArray" (the first dimension).

  8. #8
    Registered User
    Join Date
    Dec 2009
    Posts
    24
    so i changed my structure to:
    Code:
    typedef struct {
      int  rowdim, coldim;
      double** element;
    } matrix;
    and then my other code to:
    Code:
    #include "matrix.h"
    
    matrix create_empty(int rdim, int cdim)
    {
    	matrix* new_matrix;
    	new_matrix = malloc(sizeof(matrix));
    	new_matrix -> rowdim = rdim;
    	new_matrix -> coldim = cdim;
    	new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
    	return *new_matrix;
    }
    
    matrix create_initval(int rdim, int cdim, double* values)
    {
    	int i, j, k;
    	matrix* new_matrix;
    	new_matrix = malloc(sizeof(double*) * rdim);
    	new_matrix -> rowdim = rdim;
    	new_matrix -> coldim = cdim;
    	for (k=0; k<rdim; k++)
    		new_matrix -> element[k] = malloc(sizeof(double) * cdim);
    	for (i=0; i<cdim; i++)
    	{
    		for(j=0; j<rdim; j++)
    			new_matrix -> element[i][j] = values[i][j]; // does not work
    	{
    return *new_matrix;
    }
    
    void destroy(matrix a)
    {
    	free(&a.element);
    }
    }
    but im still not sure how to pass a 2d array into the function and write it to matrix

  9. #9
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    Are you going to answer my question above?

    Modifying the contents of the struct shouldn't change how the struct is passed around--you should be able to pass it/receive it the same way as with "elements" being 1D.

    I described above, you "malloc" the number of rows--once. It seems your doing this "rdim" number of times. Then you use a loop and "malloc" a column for each row, so thats when you'd use the for loop.
    Code:
    	for (k=0; k<rdim; k++)
    		new_matrix -> element[k] = malloc(sizeof(double) * cdim);
    You're using the "k"th element, without having allocated the memory for it first. Before this line, is when you'd probably allocate the memory for the rows, then this for loop should work fine for allocating each column.

    Also, you aren't "free"ing properly. Read what I said above, I'm not going to repeat it.

  10. #10
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    but im still not sure how to pass a 2d array into the function and write it to matrix
    If its an "actual" array, like you've declared it as
    Code:
    double values[3][5];
    or whatever dimensions, then you (obviously) already know the dimensions of the values array, so it would be passed like
    Code:
    void myFunction(double values[3][5])
    If you dont know the dimensions (which is probably the case), then values was probably declared like elements, like
    Code:
    double** values;
    . In this case, the function would be declared as
    Code:
    void myFunction(double** values)
    In either case, it should be called the same, like
    Code:
    myFunction(values);

  11. #11
    Registered User
    Join Date
    Dec 2009
    Posts
    24
    First off, thanks for being patient...im new to programming.

    Second the only compile errors refer to
    Code:
    for(j=0; j<rdim; j++)
         new_matrix -> element[i][j] = values[i][j]; // does not work
    it says: error: subscripted value is neither array nor pointer

    I also changed the code to:
    Code:
    for (k=0; k<cdim; k++)
    		new_matrix -> element[k] = malloc(sizeof(double) * cdim);

    the code that im compiling with the function declerations is:
    Code:
    #include "matrix.h"
    
    int main()
    {
    	double one[2][3] = {
    									     {1,2,3},
                                    {4,5,6}
    										};
    							
    
    	matrix m_one;
    	m_one = create_initval(2, 3, *one);
    	matrix_print(m_one);
    return 0;
    }

  12. #12
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    Second the only compile errors refer to
    I was referring to your initial compilation error, regarding the undefined reference. I imagine thats fixed now though.

    Next, I think I explained it well enough in my previous post (Pointer to a 2d array), as best as I could without giving you the exact solution, in which case you wont learn (i.e. a bad thing). Try and re-read it again to understand what it is saying. What I described in that post can be found online, for example, this a basic search yields this link: 23.2: Dynamically Allocating Multidimensional Arrays. The first example there is of interest.

    Try to read and understand this, then if you have a problem implementing it or you're getting an error, post all of your code and the exact and complete error/warning message(s).

  13. #13
    Registered User
    Join Date
    Dec 2009
    Posts
    24
    I understand how to set up the matrix, but im now having trouble passing in an 2d array.

    The array is set up as:
    Code:
    double one[2][3] = {
    									     {1,2,3},
                                    {4,5,6}
    										};
    							
    
    	matrix m_one;
    	m_one = create_initval(2, 3, *one);
    "one is then passed into the function:
    Code:
    matrix create_initval(int rdim, int cdim, double* values)
    {
    	int i, j, k;
    	matrix* new_matrix;
    	new_matrix -> rowdim = rdim;
    	new_matrix -> coldim = cdim;
    	new_matrix = malloc(sizeof(double*) * rdim);
    	for (k=0; k<rdim; k++)
    		new_matrix -> element[k] = malloc(sizeof(double) * cdim);
    	for (i=0; i<cdim; i++)
    	{
    		for(j=0; j<rdim; j++)
    			new_matrix -> element[i][j] = values[i][j]; // does not work
    	{
    return *new_matrix;
    }
    the program works fine, when is et "element[i][j] = number", but if it is like I have it above, i get the compile error:
    subscripted value is neither array nor pointer

    which i know is refering to the "values[i][j]"

  14. #14
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    If you declare the array of values as
    Code:
    double one[2][3]
    then the argument to the function can be the same, like
    Code:
    matrix create_initval(int rdim, int cdim, double values[2][3])
    When you call it, you dont dereference it (like you are above, by using "*"), simply pass it like
    Code:
    create_initval(2, 3, one);
    Next, inside the function in question
    Code:
    matrix* new_matrix;
    	new_matrix -> rowdim = rdim;
            // etc
    You declare a pointer and start using it without allocating it any memory. This is certainly undefined behaviour and not good. In fact, I dont think there is any point in making it a pointer, just declare it as
    Code:
    matrix new_matrix;
    Then you'll have to replace the "->"s with "."s.

    For this line
    Code:
    	new_matrix = malloc(sizeof(double*) * rdim);
    You're overwriting the stuff you just set up (setting row dim, etc). You probably want it to be
    Code:
    	new_matrix->element = malloc(sizeof(double*) * rdim);
    Of course after removing the pointer ("*"), the arrows will be dots, as described above.

    Finally, after removing the pointer, the return statement will require the "*" to be removed as its not a pointer anymore.

  15. #15
    Registered User
    Join Date
    Dec 2009
    Posts
    24
    i made all those corrections, but i still get the same compile error:
    subscripted value is neither array nor pointer - referring to:
    Code:
    new_matrix.element[i][j] = values[i][j];
    as well as a new error:
    passing argument 3 of ‘create_initval’ from incompatible pointer type
    referring to "m_one = create_initval(2, 3, one);" in:
    Code:
    #include "matrix.h"
    
    int main()
    {
    	double one[2][3] = {
    									     {1,2,3},
                                    {4,5,6}
    										};
    							
    
    	matrix m_one;
    	m_one = create_initval(2, 3, one);
    	matrix_print(m_one);
    return 0;
    }

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. prinitng 2D array form pointer ????
    By fcommisso in forum C Programming
    Replies: 6
    Last Post: 11-02-2009, 08:58 PM
  2. from 2D pointer to 1D array
    By cfdprogrammer in forum C Programming
    Replies: 2
    Last Post: 07-20-2009, 08:58 AM
  3. from 2D array to 1D array
    By cfdprogrammer in forum C Programming
    Replies: 17
    Last Post: 03-24-2009, 10:33 AM
  4. 2D array pointer
    By taurus in forum C Programming
    Replies: 15
    Last Post: 10-30-2008, 12:30 PM
  5. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21