DEV Community

Nick Alvarez
Nick Alvarez

Posted on • Updated on

Effective array chunking in C++(Intro to pointers)

Array chunking is a very common problem in programming but in most cases you will only need one large array after chunking and can disgard any subarrays used to create it. This page is going to address the more rare case of when chunking into a large array will provide efficiency but we still need the changes made to the larger array to be kept in each subarray. Instead of indexing through the larger array twice (once to set the values then once to distribute the values into each subarray) we will build a function that allows any changes made to the large array to also be made to the corresponding, allowing us to skip indexing through the large array a second time.

Visualizing the probem

Using multiple arrays

int array0[3] = {0,1,2};
int array1[3] = {3,4,5};
int array2[3] = {6,7,8};
Enter fullscreen mode Exit fullscreen mode

We want to pass these arrays into some function that will combine these into one large array

int largeArray[9] = {0,1,2,3,4,5,6,7,8};
Enter fullscreen mode Exit fullscreen mode

This function should also make it possible for each subarray to keep the changes applied to the large array. After executing these lines:

for(int i = 0; i<9; i++)
{
    largeArray[i] += 1;
}
Enter fullscreen mode Exit fullscreen mode

Printing each array should give these outputs:

Large array: 1,2,3,4,5,6,7,8,9
array0: 1,2,3
array1: 4,5,6
array2: 7,8,9
Enter fullscreen mode Exit fullscreen mode

This is an interesting problem if you haven't delt with it before and I'd encourage you to brain storm to try to come up with the answer before reading on. So without further ado, creating the function.

Creating the function

It is easy to see our regular approach of indexing through the larger array and setting each index to the corresponding integer of the subarrays won't work since changes made to the larger array won't be made to the subarrays after being set. It may already be obvious what needs to be done and if it is you're one smart cookie. Our large array will not be the same type as our subarrays, at least not really. Instead of using integer subarrays to construct a larger array of integers, we will use integer subarrays to construct a larger array of integer pointers. And instead of setting each index of the larger array to the integers of the subarray, we will set each pointer of the larger array to the memory addresses of the integers in each subarray. Cool right! But now how to code this.

How to code this

One of my all time favorite pages to help better understand how to manipulate pointers that I wish I could take credit for is here. But without further ado. Here's the code.

void Executive::Combine(int size, int * Holder[], int input0[], int input1[], int input2[])
{
        for(int i = 0; i<size; i++)
        {
                Holder[i] = &input0[i];
                Holder[i+size] = &input1[i];
                Holder[i+size*2] = &input2[i];
        }
}
Enter fullscreen mode Exit fullscreen mode

A simple function to understand once you know what the ampersand is used for. The ampersand is used to set the memory address rather than the value of the memory address the pointer is pointing to. So in this case we are first setting the pointer of 'Holder' at index 'i' to the memory address of our 'input0' at index 'i'. As 'i' increases we will fill the Holder array with the proper memory addresses of the subarrays allowing any changes made to the larger area to be carried to each subarray.

Testing

Here lets build some code to test out our function.

int array0[3] = {0,1,2};
int array1[3] = {3,4,5};
int array2[3] = {6,7,8};
int * largeArray[9];

Combine(3,largeArray,array0,array1,array2);

cout<<"After combining:"<<endl;
for(int i=0; i<9; i++){
        cout<<*largeArray[i];
}
for(int i=0; i<9; i++){
        *largeArray[i]+=1;
}
cout<<endl<<"After addition:"<<endl;
for(int i=0; i<9; i++){
        cout<<*largeArray[i];
}
cout<<endl<<"array0:"<<endl;
for(int i=0; i<3; i++){
        cout<<array0[i];
}
cout<<endl<<"array1:"<<endl;
for(int i=0; i<3; i++){
        cout<<array1[i];
}
cout<<endl<<"array2:"<<endl;
for(int i=0; i<3; i++){
        cout<<array2[i];
}
Enter fullscreen mode Exit fullscreen mode

You may have noticed that a few stars * are slipped into the code. That's because this symbol is used to accessing a pointers value. All the other arrays used are just integer arrays so there's no need to use them there. Without using stars on a pointer you'll be printing the actual memory addresses of the pointers and you may end up printing something like this.

After addition:
0xffffcb8c0xffffcb900xffffcb940xffffcb800xffffcb840xffffcb880xffffcb740xffffcb780xffffcb7c
Enter fullscreen mode Exit fullscreen mode

Desired outputs

After combining:
012345678
After addition:
123456789
array0:
123
array1:
456
array2:
789
Enter fullscreen mode Exit fullscreen mode

I hoped this helped provide you with a better understanding of how to manipulating pointers and their usefulness. I wish you the best of luck in your endeavors. Thanks for reading!

Top comments (0)