[try Beta version]
Not logged in

 
Array pointers.

Pages: 12
Sep 7, 2015 at 5:07am
This is for a class assignment. I have to set up three levels of indirection of pointers to an array of ints.

What I have tried so far is this.

1
2
3
 int ***s = new int **[row];
*s = new int *[row];
**s = new int[row];


But I feel like this is not exactly what I'm suppose to be doing. So I tried doing it this way.

1
2
3
4
5
6
7
int ***s = new int **;
*s = new int*;
**s = new int[row];
**s = 1;
**(s + 1) = 2;

cout << **s[0];


It compiles and I can assign a value to the first element in the array and output one, but I cannot assign anything to the second element and it crashes when I try to output it. Any help would be appreciated.

I have to do a whole mess of other functions to go along with this but I cant even get the base working, its driving me mad!
Last edited on Sep 7, 2015 at 5:08am
Sep 7, 2015 at 6:27am
Almost!

to access an element in the array:
1
2
3
4
*s = new int*;
**s = new int[row];
***s = 0;             //first element to 0
(**s)[1]=1;          // second element to 1 
Last edited on Sep 7, 2015 at 6:28am
Sep 7, 2015 at 8:27am
Ah okay, thank you very much, I also have a follow up question. I'm trying fill that array with int to pointers, so I would have that array filled with other arrays to create a dynamic 2d array. What I have tried isn't working because of the type mismatch int * to int but I'm not sure how to go about it.

1
2
for (int i = 0; i <= column; i++)
      *(**s + i) = new int [column];
Last edited on Sep 7, 2015 at 8:31am
Sep 7, 2015 at 9:20am
*(**s + i)Accesses a specific int (you have three levels of indirection and three dereferences, so in the end you have int). Compare
1
2
3
int* i = nullptr;
*i = new int[100]//Incorrect
i = new int[100]; //Correct 


So you need to drop outside dereference. Also your addition in wrong place: you meant to change second-level pointer, which points to arrays of ints, but changing third level one, which points to individual ints. Correct code: *(*s + i) = new int [column];

Note that *(x + y) is equal to x[y]. So it would be better to use *s[i] = new int [column]; as it conveys that it is an array of arrays. If you will make your top-level pointer an array too (3D array), then it would be even better to use this: s[0][i] = new int [column];
Sep 7, 2015 at 9:43am
Hmm maybe I misunderstood your post, I tried,

1
2
for (int i = 0; i <= column; i++)
	*s[i] = new int [column];


and it compiles but crashes inside the loop after one iteration.
Last edited on Sep 7, 2015 at 9:43am
Sep 7, 2015 at 9:47am
Ah, subscripting has higher precedence than dereference, right. You need (*s)[i]. Did you allocate memory to s and *s too?
Sep 7, 2015 at 10:07am
Yeah that works, good grief this is confusing.

1
2
3
4
5
6
7
int ***s = new int **;
	*s = new int*;
	**s = new int[row];

	for (int i = 0; i <= column; i++)
		(*s)[i] = new int[column];


This is what I have, and it compiles. On line three its creating the rows array and the for loop is filling that array with column arrays correct? So (*s)[i] is accessing rows elements and

 
(*s)[0][1];


Would be accessing rows base and the second element in columns?

Also this is equivalent to above, correct?
 
**(*(s + 0) + 1) = 5;
Sep 7, 2015 at 10:32am
1
2
**s = new int[row];
(*s)[i] = new int[column];
This is memory leak. **s is (*s)[0]
You are assigning to that pointer at frst iteration again. In addition to that, *s is a single int pointer and not an array pointer, so you have buffer overrun here.

Correct way:
1
2
3
4
5
6
7
8
int*** s = new int**; //Assuming you do not want 3D array
*s = new int*[rows];
for (int i = 0; i < rows; ++i) //Note < and rows
    (*s)[i] = new int[columns];
//Access
for (int row = 0; row < rows; ++i)
    for (int column = 0; column < columns; ++i)
        (*s)[row][column] = 0; //Set all values to 0 
Sep 7, 2015 at 12:39pm
closed account (48T7M4Gy)
Good. And don't forget to delete as MiiNiPaa might like to demonstrate.
Sep 7, 2015 at 1:05pm
It might be easier to understand if you break it down into functions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Make a 1 dimensional array with "size1" elements
int *make1D(size_t size1)
{
    return new int[size1];
}

// Make a 2D array
int **make2D(size_t size2, size_t size1)
{
 // 1st dimension is array of pointers to 1D arrays
    int **result = new int*[size2];

    // Now fill in each element of 1st dimension with a 1D array
    for (size_t i=0; i<size2; ++i) {
	result[i] = make1D(size1);
    }
    return result;
}

// Make a 3D array
int ***make3D(size_t size3, size_t size2, size_t size1)
{
    // 1st dimension is pointers to pointers to 2D arrays
    int ***result = new int**[size3];

    // Now fill in each element with a 2D array
    for (size_t i=0; i<size3; ++i) {
	result[i] = make2D(size2, size1);
    }
    return result;
}
Sep 7, 2015 at 2:04pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <memory>

int*** new_array( std::size_t x, std::size_t y, std::size_t z )
{
    int* array = new int[x*y*z] {} ;

    int** array2 = new int* [x*y] {} ;
    for( std::size_t i = 0 ; i < x*y ; ++i ) array2[i] = array + i*z ;

    int*** array3 = new int** [x] ;
    for( std::size_t i = 0 ; i < x ; ++i ) array3[i] = array2 + i*y ;

    return array3 ;
}

void delete_array( int*** array3 )
{
    delete[] array3[0][0] ;
    delete[] array3[0] ;
    delete[] array3 ;
}

namespace smart
{
    using array3 = std::unique_ptr< int**[], decltype(&::delete_array) > ;

    array3 make_array( std::size_t x, std::size_t y, std::size_t z )
    { return array3( ::new_array(x,y,z), &::delete_array ) ;}
}

int main()
{
    const std::size_t x = 3, y = 4, z = 5 ;

    {
        auto a3 = new_array( x, y, z ) ;

        int n = 10 ;
        for( std::size_t i = 0 ; i < x ; ++i )
        {
            for( std::size_t j = 0 ; j < y ; ++j )
            {
                for( std::size_t k = 0 ; k < z ; ++k ) std::cout << ( a3[i][j][k] = ++n ) << ' ' ;
                std::cout << '\n' ;
            }
            std::cout << '\n' ;
        }

        delete_array(a3) ;
    }
    std::cout << "\n-------------------------\n\n" ;
    {
        auto a3 = smart::make_array(x,y,z) ;

        int n = 10 ;
        for( std::size_t i = 0 ; i < x ; ++i )
        {
            for( std::size_t j = 0 ; j < y ; ++j )
            {
                for( std::size_t k = 0 ; k < z ; ++k ) std::cout << ( a3[i][j][k] = ++n ) << ' ' ;
                std::cout << '\n' ;
            }
            std::cout << '\n' ;
        }
    }
}

http://coliru.stacked-crooked.com/a/59b45c3703353544
Sep 7, 2015 at 7:16pm
I see, but wouldn't MiinPaa's solution only be two levels of indirection?


I need to set up a table like so,
[ s ] - > [ s ] - > [ s ] - > [Array]


Also dhayden thank you, I think I'm starting to understand, but I just don't see the value in indirection other then confusion.

And JLBorges isn't that a three dimensional array?
Sep 7, 2015 at 7:51pm
Does last s should point to first element to the array (act as array pointer) or point to actual array pointer? Because in later case you would need an extra level of indirection.

Just to clarify, you want this, right? http://puu.sh/k3nFf/40909a5043.png

In this case you need to allocate memory for *s and store it in s, then allocate memory for **s and store pointer to it in *s, and then you need to allocate memory for whole array of int and store pointer to it in **s

Edit: better diagram
http://puu.sh/k3tGD/6dab2b3e1e.png
Last edited on Sep 7, 2015 at 9:13pm
Sep 8, 2015 at 12:18am
Wouldn't that create just an array of ints? if I had,

1
2
3
int*** s = new int**;
*s = new int*;
**s = new int[row];
Last edited on Sep 8, 2015 at 12:19am
Sep 8, 2015 at 12:31am
> And JLBorges isn't that a three dimensional array?

Three one-dimensional arrays, set up to have a three-dimensional array view of a one-dimensional array of integers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int*** new_array( std::size_t x, std::size_t y, std::size_t z )
{
    int* array = new int[x*y*z] {} ; // one-dimensional array of x*y*z int

    int** array2 = new int* [x*y] {} ;  // one-dimensional array of x*y pointers to int
    for( std::size_t i = 0 ; i < x*y ; ++i ) array2[i] = array + i*z ;
    // this gives us a view of array as a two-dimensional array 
    // eg. array2[i][j] yields array[ i*z + j ]

    int*** array3 = new int** [x] ; // one-dimensional array of x pointers to pointers to int
    for( std::size_t i = 0 ; i < x ; ++i ) array3[i] = array2 + i*y ;
    // this gives us a view of array as a three-dimensional array 
    // eg. array3[i][j][k] yields array2[ i*y + j ][k] ie. array[ ( i*y + j ) * z + k ]

    return array3 ;
}

void delete_array( int*** array3 )
{
    delete[] array3[0][0] ; // delete one-dimensional array of int
    delete[] array3[0] ; // delete one-dimensional array of pointers to int
    delete[] array3 ; // delete one-dimensional array of pointers to pointers to int
}
Sep 8, 2015 at 4:49am
Wouldn't that create just an array of ints?
Isn't it is what you told you want:
I need to set up a table like so,
[ s ] - > [ s ] - > [ s ] - > [Array]


Explain what is the result you wnat to get in the very end.
Sep 8, 2015 at 5:40am
Indirection (for diagram in MiiNiPaa's link) without dynamic allocation:
1
2
3
4
5
6
7
8
9
10
11
int array [] {1, 2, 3, 4, 5, 6 };
int   * one = array;
int*  * two = &one;
int** * s = &two;

assert( 1 == s[0][0][0] );
assert( 2 == (*s)[0][1] );
assert( 3 == (**s)[2] );
assert( 4 == s[0][0][3] );
assert( 5 == (*s)[0][4] );
assert( 6 == (**s)[5] );

In the dynamically allocated version the "two", "one" and "array" are nameless objects in the free store.
Sep 8, 2015 at 6:30am
The table I actually need is,


[ s ] - > [ s ] -> [ s ] - > [ Array of int pointers pointing to ints, for 2d array ]
___[ f ] -^
[ z ] -> [ z ] -> [ z ] --------^
___[ h ]-^

I'm just trying to sort out the first bit.
Last edited on Sep 8, 2015 at 6:31am
Sep 8, 2015 at 8:26am
Ah, so you do need additional level of indirection. In this case s should be int**** s
Other than that, everything like earlier, but with additional level of indirection added. If you are allowed to, use keskiverto approach without dynamic allocations (or at last minimise them: only array should be in dynamically allocated)
Sep 8, 2015 at 9:13am
Hm, I was told that counting the arrows is a good way to tell level of indirection.

1
2
3
4
5
int ***a = new int**;
*a = new int*;
**a = new int;
***a = 18


This was an example I found on three levels of indirection, I feel adding another int**** s; would make this four levels of indirection, no?
Pages: 12