Array pointers.

Pages: 12
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
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
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
*(**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];
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
Ah, subscripting has higher precedence than dereference, right. You need (*s)[i]. Did you allocate memory to s and *s too?
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;
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 
closed account (48T7M4Gy)
Good. And don't forget to delete as MiiNiPaa might like to demonstrate.
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;
}
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
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?
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
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
> 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
}
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.
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.
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
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)
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