Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Undefined Reference

  1. Jun 20, 2007 #1
    I'm trying to call a function from a .o file, and it keeps telling me:

    "undefined reference to ..." where the ... is whatever function I'm trying to call.

    Do any of you have any idea what's wrong with this?
  2. jcsd
  3. Jun 20, 2007 #2

    jim mcnamara

    User Avatar

    Staff: Mentor

    How did you compile your code - what command did you use?
    A .o file has to be linked into your code (C example)
    Code (Text):

    cc myfile.c anotherfile.o -o myfile
  4. Jun 20, 2007 #3
    I figured it out, I had wrong capitalization of the function name.

    Next question:

    If I have a pointer to the first element of a dynamically allocated 2 dimension array, is there any way to use two subscripts with that pointer.
    Code (Text):

    //I create a dynamically allocated array:
    int i;
    int N = 100;
    double **A;
    double *p;
    A = new double *[N]
    for(i = 0; i < N; i++) A[i] = new double [N];

    // and point a pointer to the first element.
    p = A[0];

    //now I want to be able to use it like this:

    p[3][4] = 12;
  5. Jun 20, 2007 #4


    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    C really has no concept of multi-dimensional arrays; all arrays are really stored in a one-dimensional format in memory. When you want to access element [3][4], the compiler actually performs some math to get a one-dimensional index: 3 * (number of elemts in row) + 4. If the compiler doesn't know how many elements are in a row, it cannot do this.

    So, if all you're given is a pointer to the first element of a multidimensional array, you are effectively screwed.

    - Warren
  6. Jun 20, 2007 #5
    There's no way to typecast it, if you know the number of elements in the row?
  7. Jun 20, 2007 #6


    User Avatar
    Homework Helper

    Your code creates an array of pointers, this is not a matrix.

    In the matrix examples below, note that "double (*pmd)[5]" declares pmd to be a pointer to an array of 5 doubles,
    as opposed to "double *pmd[5]" which is an array of 5 pointers to double; the parenthesis around *pmd is what makes the difference.

    C++ matrix example:

    Code (Text):

        double (*pmd)[5] = new double[4][5];
        pmd[1][2] = 1.0;
        delete [] pmd;
    C++ array with matrix typecast example:
    Code (Text):

        double *pad = new double[20];
        ((double (*)[5])pad)[1][2] = (double) 1.0;
        delete []pad;
    C matrix:
    Code (Text):

        double (*pmd)[5] = (void *)malloc(4*5*sizeof(double));
        pmd[1][2] = 1.0;
    C array with matrix typecast:

    Code (Text):

        double *pad = (void *)malloc(4*5*sizeof(double));
        ((double (*)[5])pad)[1][2] = 1.0;
        free((void *)pad);
    Using Microsoft compiler, all 3 examples produce essentially the same code:
    allocate 160 bytes,
    set [ptr+56] = [ptr + (((1 x 5) + 2) x sizeof(double))] to 1.0
    free ptr.
    Last edited: Jun 21, 2007
  8. Jun 21, 2007 #7
    Can you do this if you need both dymensions to be dynamically allocated?

    This is what I was looking for. Thank you.
  9. Jun 21, 2007 #8


    User Avatar
    Homework Helper

    Not with the Microsoft compilers. Only the first dimension of a muti-dimensional array is allowed to be dynamic, the rest have to be compile time constants. You would need to use a vector of pointers to accomplish the equivalent, and would have to iterate for each allocation and/or freeing of a vector. The entity would be a mix of pointers and doubles.

    In the examples above, what I really created was a pointer to an vector of 5 doubles, such as "double (*pv)[5]". C and C++ allow pv[j] or (*pv+i)[j], effectively promoting the pointer to a vector to a pointer to a matrix.

    For a more familiar example, "double *ps" is a pointer to a scalar double (just one instance), and C and C++ allow ps or *(ps+i), effectively promoting the pointer to a scalar to a pointer to a vector.

    Here is an example that actually uses a pointer to a matrix:
    Code (Text):

        static double *ps = new double[40];         // poitner to scalar
        double (*pv)[5] = (double (*)[5])ps;        // pointer to vector
        double (*pm)[4][5] = (double (*)[4][5])ps;  // pointer to matrix
        ps[6] = 1.0;                                // *(ps +  6) = 1.0
        pv[1][2] = 1.0;                             // *(ps +  7) = 1.0
        (*pm)[3][4] = 1.0;                          // *(ps + 19) = 1.0
        pm[1][2][3] = 1.0;                          // *(ps + 33) = 1.0
        delete [] ps;
    Last edited: Jun 21, 2007
  10. Jun 21, 2007 #9

    My code from post 3 works to create a two dimensional dynamically allocated array. Try it. I don't understand why you tell me that it doesn't work.

    Code (Text):

    //next two lines create a dynamically allocated N by M array A[N][M]
    double **A = new double *[N];
    for(i = 0; i < N; i++) A[i] = new double[M];

    //we can then use it like this
    A[1][3] = 14;
    cout << A[1][3];
    What I was asking was not how to create the array (though if there is a better way, I'd be glad to hear it, this method always seemed inelegant to me), but if I later have a pointer pointing to the first element of the array, how to use it with two subscripts.

    Code (Text):

    //make a pointer and point it to the first element of A
    double *p;
    p = A[0];

    //I wanted to be able to use p something like p[1][3]
    //you gave me the answer by typecasting the pointer

    ((double (*)[M])p)[1][3] = 14;
    cout << ((double (*)[M])p)[1][3];
  11. Jun 21, 2007 #10

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    You are talking past one another, thanks to how C (and C++) treats multi-dimensional and ragged arrays. Jeff Reid is creating multi-dimensional arrays while NeoDevin is creating ragged arrays. A multi-dimensional array occupies a monolithic block of memory and is allocated by a single new/malloc, while a ragged array comprises multiple chunks of memory and requires multiple new/malloc invocations. Both are accessed the same way: [noparse]multi_dim_array[index1][index2][/noparse] versus [noparse]ragged_array[index1][index2][/noparse].
  12. Jun 21, 2007 #11


    User Avatar
    Homework Helper

    You can't. You need a pointer to one of the pointers in A in order to use two subscripts. If you just copy the first pointer in A to a pointer to double, "p = A[0]", there's no way to get to A[1], A[2], ..., from p, because the vector of pointers only exists in A, while p only contains a single pointer. You'd have to create a duplicate of A, a pointer to a pointer to a double. You can implement this with just two allocated chunks of memory, by allocating a large vector, then setting A[] to sequentially higher locations in the large vector:
    Code (Text):

    int main()
        int i0, i1;                         // indexes
        int d0, d1;                         // dimension sizes

        d0 = 4;
        d1 = 5;

        double **apd = new double *[d0];    // allocate vector of pointers
        double *pd = new double[d0*d1];     // allocate large vector of doubles

        double *pt = pd;                    // temp pointer to vector of doubles
        for(i0 = 0; i0 < d0; i0++){         // set pointers to vectors of doubles
            apd[i0] = pt;
            pt += d1;}

        double **ppd = apd;                 // copy of apd;

        for(i0 = 0; i0 < d0; i0++)          // access the data
            for(i1 = 0; i1 < d1; i1++)
                ppd[i0][i1] = 1.0*i0*i1;

        delete [] pd;                       // delete large vector of doubles
        delete [] apd;                      // delete vector of pointers

    I already mentioned this in post #6: "Your code creates an array of pointers, this is not a matrix."
    Last edited: Jun 21, 2007
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook