Thread: Modifying an array from within a function

  1. #1
    Guest
    Guest

    Modifying an array from within a function

    Hello, this is my first post. I'm fairly new to programming and i have some uncertainty regarding the manipulation of arrays through a function that they are passed to.

    The context is a matrix transformation, where i want to call a function with an array m[4][4] and a few transformation parameters as its arguments.

    Code:
    void matrixTransform(double *m, double rx, double ry, double rz, double tx, double ty, double tz)
    {
        /* Here i do a few mathematical calculations.
            Essentially, i want to set m = m * mt, where mt is an array[4][4]
            that is built from the (rx, ry, ...) parameters on each function
            call.
        */
    }
    I have browsed related questions here on the forum and elsewhere on the web, but they don't address my confusion, so i though i'd go through it step by step to finally get clarity.

    My question is regarding the proper syntax for handling arrays passed to functions. (1) Do i understand it correctly, that an asterisk needs to be placed before first parameter m, because the function is to expect an array (pointer)?

    (2) And are these two lines equivalent in meaning/behavior?
    Code:
    void matrixTransform(double *m) {...}
    void matrixTransform(double m[]) {...}
    (3) I have also seen the use of
    Code:
    function(double **var)
    in relation to array handling, which confused me even more.

    (4) Since my code does an (abstractly described) m = m * mt assignment, i suspect i need to create a copy of m within the function, so that i can read from it's original contents, while writing new ones to it.

    e.g.
    Code:
    void matrixTransform(double *m)
    {
        /* (again, pseudo-code because it's redundant to type it all out)
            these are 2D arrays of size [4][4]. */
        m2 = m;
        m = m2 * mt;
    }
    (5) What would be a robust but fast method to create this copy? A simple declaration of m2 followed by a for-loop to transfer m's contents to it?




    Regarding array manipulation, if i write this code:
    Code:
    void matrixTransform(double *m)
    {
        m[2][3] = 5;
    }
    (6) Have i effectively changed a value in m's original address space? I imagine this would be most desirable for an array that iteratively gets its values modified, but where size (16 x 8 bytes) stays constant.

    (7) Also, am i right in thinking the function can be of type void, as i'm not returning a value but manipulating a pre-existing array?


    Sorry for all the questions. Not 'getting it', i simply don't want to use trial and error in C; it's too easy to mess up.

    Adrian
    Last edited by Guest; 01-01-2013 at 05:15 PM.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    2. Yes

    3. Well, pointers can emulate arrays. So var was set up to point to some pointers, which pointed to the actual memory being used as an array.

    4. From what I remember on matrix multiplication, you will need a separate matrix for the answer and not necessarily copies of the operands, because the operands stay the same but the answer has a different shape.

    5. Unless I'm not getting something, this is irrelevant.

    6. [edit] Yes you changed a value in m. Specifically the third value down, and fourth across. I misread the question. [/edit]

    7. Yes.

    What actually happens when you pass in a multidimensional array to a function is that the first dimension becomes a pointer to the other dimensions. The other dimensions will stay array type. They need to have their dimension sizes specified or there will be a compiler error.

    There can be subtle differences between types:
    Code:
    void matTransform (double (*m)[5] ); /* OK */
    void matTransform2(double m[][5] );  /* OK */
    void matTransform3(double *m[5] );   /* wrong - m is an array of 5 pointers to double */
    void matTransform4(double **m );     /* dimensions aren't specified; can only work for variables starting out as double **m */
    void matTransform5(double m[][] );   /* error: array type has incomplete element type */
    Last edited by whiteflags; 01-01-2013 at 05:41 PM.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    6. won't compile. vc2012 gives the error "error C2109: subscript requires array or pointer type". you passed in a pointer, which resolves to a single indexed array. the compiler doesn't know the extents of the columns so it can't compile it.

    if your function needs to operate on a 2d array, you can use whiteflags declaration "void matTransform2(double m[][5] );" if the coumn extent is known at compile time, or you can pass in the bare pointer "double *m" and compute the array index yourself. for a 2d array, it would be "index = row * column_length + col. you would need to pass in or otherwise know at least the column extent to make the computation, which is what the compiler does with the "double m[][5]" declaration. If the row and column extents are not fixed at compile time, I usually pass in the row and column extents and do the computation of the index as shown.

    when i have uncertainty about pointers, I draw a diagram of the variables involved and what is pointing to what.

  4. #4
    Registered User
    Join Date
    May 2012
    Posts
    505
    Multidimensional arrays don't work well in C.

    The way that an experienced C programmer would handle your problem is like this.

    Code:
    typedef struct
    {
       double mtx[4][4];
    } MATRIX;
    
    /*
      this function translates a 3D matrix by x,y and z, passed
        in the second parameter.
      (note you might want the last row instead of the last column if
       your system is set up the other way round). 
    */
    void matrixTransform(MATRIX *m, double *translation)
    {
       m->mtx[0][3] += translation[0];
       m->mtx[1][3] += translation[1];
       m->mtx[2][3] += translation[2];
    }
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  5. #5
    Guest
    Guest
    Thank you for your answers everyone.

    Malcolm: What would you say is the problem with multidimensional arrays? Does the struct solve help this, or is it just for readability? I could use an array[16] instead of [4][4] but i prefer the latter for the sake of readability (it's easier to think in rows/columns).

    dmh2000: I have now changed the function parameter to m[4][4] instead of *m, as i know the size in advance. Thanks.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Guest
    What would you say is the problem with multidimensional arrays? Does the struct solve help this, or is it just for readability?
    Heh, the 2D array is still there, so it is not that "multidimensional arrays don't work well in C". The advantage here is abstraction: instead of thinking in terms of and passing around a 2D array (which really decays to a pointer to its first element), you now think in terms of a matrix and pass around a matrix (using a pointer to avoid unnecessary copying).

    With this abstraction, at some later point you may choose to have matrices of flexible size, e.g., by using pointers to dynamically allocated memory and storing the dimensions in the matrix object.
    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

  7. #7
    Guest
    Guest

    Thanks, it works!

    It was a success, my first real program works as intended and is about 20 times faster than my Python/Numpy implementation.
    I familiarized myself with structs as you suggested, and it has really helped me. I think i will be moving to C++, as the object oriented approach makes working with these things a lot easier to keep track of.

    On the off-chance that someone searches the forum for a similar question, specifically matrix transformations, i want to mention the following findings:

    • Reducing the calculations for affine transformations, by leaving out permanently untouched "0"s of the matrix, actually hurts performance. Puzzling. maybe the non-sequential readout is harder to optimize for the the compiler.
    • Edit: Using array[16] instead of array[4][4] is negligible to performance.
    Last edited by Guest; 01-06-2013 at 09:13 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Modifying a program to use a function
    By cnoviceirish in forum C Programming
    Replies: 2
    Last Post: 12-06-2012, 01:23 PM
  2. K&R Exercise 1-16: Modifying a getline() function
    By edw211 in forum C Programming
    Replies: 5
    Last Post: 06-15-2011, 03:58 PM
  3. modifying bubblesort function
    By tenhavenator in forum C Programming
    Replies: 3
    Last Post: 11-14-2009, 12:54 AM
  4. Modifying an element in an array
    By Martin_T in forum C Programming
    Replies: 3
    Last Post: 11-04-2009, 09:10 PM
  5. Modifying a char array in VC++ 6 ide.
    By clu82 in forum Windows Programming
    Replies: 5
    Last Post: 03-18-2003, 01:56 PM