Thread: Matrix on stack to int**... How?

  1. #1
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64

    Matrix on stack to int**... How?

    Code:
    #include <iostream>
    using namespace std;
    
    int main() {
      int matrix [3][3];
      for (unsigned int i = 0; i < 3; ++i) {
        for (unsigned int j = 0; j < 3; ++j) {
          matrix [i][j] = 0;
        }
      }
      int** matrix_as_a_pointer = &(&(matrix[0][0]));
      return 0;
    }
    Why is it that I can't do this? What's the best way to have an int** for a matrix on the stack? Thank you in advance.
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    int** matrix_as_a_pointer = matrix;
    If you want to get a pointer to a location somwhere within the array, it would be:
    Code:
    int** matrix_as_a_pointer = static_cast<int **>&matrix[y] [x];
    or
    Code:
    int** matrix_as_a_pointer = &matrix[y] + x;
    or slightly more complex:
    Code:
    int** matrix_as_a_pointer = matrix + y * 3 + x;
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    Code:
    int** matrix_as_a_pointer = &(&(matrix[0][0]));
    What is this??

    Your rvalue is trying to get a pointer from a pointer to the first varible in the matrix.
    If you want to get a pointer to the matrix just do like this:
    Code:
    int ***matrix_as_a_pointer = &matrix;
    EDIT:
    matsp - you posted while I was writing.

    Don't do that.

  4. #4
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    Is that really supposed to work? I'm getting a segmentation fault on Ubuntu Linux by using:

    Code:
    int** matrix_a_as_a_pointer = (int**)matrix_a; //If I omit the cast, the compiler produces a warning
    printf("&#37;d\n, matrix_a_as_a_pointer[0][0]");
    And yes, matrix_a[0][0] is properly initialized.
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, of course. The double pointer will need to point to a pointer, which in turn points to the array content.

    What are you ACTUALLY trying to do? In a bigger picture, that is.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    I wish I could post the whole code here, but this is part of an assignment. Some of my colleagues would definitely resort to copying and pasting my code and calling it their own.

    I can tell you this much: I want to have a char* with one of the matrix's lines. I created a function that does that whose prototype is
    Code:
    char* getLine(int*** matrix, unsigned int line, unsigned int limit);
    So, if I want to get the matrix's line 0, i'd do
    Code:
    getLine(&matrix, 0, 3);
    That is, if "matrix" is an int**, and if it has 3 columns.

    However, using gdb, I found out this was giving me a segmentation fault when I tried to do, for instance, (*matrix)[0][0] ("matrix" is now an int***, since it was passed to the function as such). I am unable to understand why. The matrix is properly initialized.

    I'm sorry I can't provide more information. If this means you are unable to help me, then I understand I'm on my own. Nonetheless, thank you for your time.
    Last edited by Mr_Miguel; 10-11-2007 at 08:45 AM.
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, I can help you, it's just that sometimes someone asks detailed questions, where the overall problem can be solved a differnet way.

    So, essentially, you need to create another array:
    Code:
    int *matrix_rows[3];
    int **matrix_ptr;
    for(i = 0; i < 3; i++)
      matrix_rows[i] = &matrix[i][0];
    matrix_ptr = matrix_rows;
    The above is just a sketch, it may need some "fixing", but I think it shows you the principle.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    Well, the whole point of my question was to avoid copying things (in your case, pointers) to other locations. However, I'll have to resort to that if I run out of options anyway.
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You are not copying things when you call the function - but a pointer to pointer must point to a valid memory address when you use ptr[y][x], because it's the same as *(*(ptr + y) + x). As you can see, there are two pointer dereferences - one for the (ptr + y), and then another for that address plus x.

    The other option is to make it a pointer to int, and reference it with
    Code:
       matrix[x + y * hor_size];
    This is what the compiler does anyways, but it gets complicated when the indexes are complex (e.g matrix[y*2+3][x-5] is much easier to read than matrix[x-5 + (y*2+3) * hor_size];

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by Mr_Miguel View Post
    However, using gdb, I found out this was giving me a segmentation fault when I tried to do, for instance, (*matrix)[0][0] ("matrix" is now an int***, since it was passed to the function as such). I am unable to understand why. The matrix is properly initialized.
    A 2D (or more) stack array has a unique type that cannot be properly converted to a pointer type. As a result you cannot return a 2D stack array. Essentially the problem is that 2D stack arrays are handled as a 1D array, and the pointers to the beginning of each row are never stored, but rather are computed as needed.

    The solutions are:
    Return a 2d heap array (via pointer). This can be a problem because of memory management, in particular you should avoid having a function return a memory address it allocated.

    Pass the 2d array as a parameter. Arrays are implicitly passed by reference. You can also create array references in your function body.

    Return a vector of vectors of your type. This is usually the best way.

    There are libraries that provide multidimensional array containers that are better than nested vectors because each row is required to be of the same length. You can use them. I believe boost has such a container.
    Last edited by King Mir; 10-11-2007 at 09:28 AM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by King Mir View Post
    A 2D (or more) stack array has a unique type that cannot be properly converted to a pointer type. As a result you cannot return a 2D stack array. Essentially the problem is that 2D stack arrays are handled as a 1D array, and the pointers to the beginning of each row are never stored, but rather are computed as needed.

    The solutions are:
    Return a 2d heap array (via pointer). This can be a problem because of memory management, in particular you should avoid having a function return a memory address it allocated.

    Pass the 2d array as a parameter. Arrays are implicitly passed by reference. You can also create array references in your function body.

    Return a vector of vectors of your type. This is usually the best way.

    There are libraries that provide multidimensional array containers that are better than nested vectors because each row is required to be of the same length. You can use them. I believe boost has such a container.
    Well, technicaly, you can pass a stack array around using this method:
    Code:
    func(int arr2d[][20], ...) ...
    The problem with any multidimensional arrays is that you do need to know the size of all dimensions besides the left-most one, because all C arrays are essentially 1D arrays, with a suitable calculation to achieve the location of the dimensions. The same applies when you allocate on the heap or if you create a global variable -it is only chunk of linear memory in every case.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    I think I got it, guys. I think I have the cause of my problem. See the attachment.

    Is it correct to conclude that A + 1 (i. e. ponteiro_matriz_a + 1) points to [0][1], when what I actually would want would be for it to point to [1][0]?

    EDIT: Never mind. I get it now. My int** has the first element's address. ponteiro_matriz_a[0][0] is equal to **ponteiro_matriz_a. Therefore, I dereference that pointer twice. The first time I dereference it, I get the matrix's first value, as an int*. On my case, that value is 1, or, in hexadecimal, 0x1. When I dereference it again, I attempt to access whatever it is at the address 0x1. But there's nothing there. That's why it's giving me a segmentation fault.

    Note to self: never convert an integer 2D array to an int**.
    Last edited by Mr_Miguel; 10-11-2007 at 11:07 AM.
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  13. #13
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by matsp View Post
    Well, technicaly, you can pass a stack array around using this method:
    Code:
    func(int arr2d[][20], ...) ...
    The problem with any multidimensional arrays is that you do need to know the size of all dimensions besides the left-most one, because all C arrays are essentially 1D arrays, with a suitable calculation to achieve the location of the dimensions. The same applies when you allocate on the heap or if you create a global variable -it is only chunk of linear memory in every case.

    --
    Mats
    Yeah, that's what I meant by Pass the 2d array as a parameter. You can also do this to force the first parameter to be the same:
    Code:
    void func(int (&arr2d)[10][20]);
    This also has the effect of making sizeof(array) be the actual size of the array.
    Last edited by King Mir; 10-11-2007 at 11:52 AM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  14. #14
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by King Mir View Post
    Code:
    void func(int (&arr2d)[10][20]);

    TO make the parameter a pointer to an array[10][20] of ints, it should be:
    Code:
    void func(int (*arr2d)[10][20]);
    Of course, functions defined like this will only work for that particular size array (which, I think, will not help whatever it is that the Original Poster is trying to accomplish).

    D.
    Last edited by Dave Evans; 10-11-2007 at 01:37 PM.

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    TO make the parameter a pointer to an array[10][20] of ints, it should be:
    King Mir wanted to demonstrate how to pass an array such that it does not decay to a pointer to its first element. It probably is not very useful since one needs to know the size of the array in order to write the function in the first place, in which case one could use the array size in the function directly.

    I think that your example offers no advantage over King Mir's example, but is more complex. Either way, the array size can be directly used in the function, whether by hardcoding or through a constant since it is specific to the function and its array parameter.

    It would be more flexible to pass the array such that it decays to a pointer to its first element, and then just provide the array size as another argument. Better yet, one could use a standard container such as std::vector.
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Matrix Help
    By HelpmeMark in forum C++ Programming
    Replies: 27
    Last Post: 03-06-2008, 05:57 PM
  2. stack and pointer problem
    By ramaadhitia in forum C Programming
    Replies: 2
    Last Post: 09-11-2006, 11:41 PM
  3. Question about a stack using array of pointers
    By Ricochet in forum C++ Programming
    Replies: 6
    Last Post: 11-17-2003, 10:12 PM
  4. error trying to compile stack program
    By KristTlove in forum C++ Programming
    Replies: 2
    Last Post: 11-03-2003, 06:27 PM
  5. Stack Program Here
    By Troll_King in forum C Programming
    Replies: 7
    Last Post: 10-15-2001, 05:36 PM