I am trying to utilise a development kit for software that we use at work.

I think I have found a member function that would address a problem I have and I'm trying to test it.

The documentation says that it is used thus:

int
SDKclass::SDKclassmethod(
a_data_type** a_data_array_ptr,
char*** b_array_ptr, 
int& num, 
c_data_type c_data_inst)

My problem is that I cannot understand the usage of the 2nd input b_array_ptr. I believe it is a pointer to an array of char arrays. This would be a logical format for the variable. However, I cannot find a way of initialising it that my compiler (MSVS2008) is happy with.

I have tried just declaring it but not initialising it:

a_data_type *a_data_array, **a_data_array_ptr;
char*** b_array_ptr;
int numFtrs;
//code where a value is given to numFtrs - I know this works fine
a_data_array = new a_data_type[numFtrs];
a_data_array_ptr = &a_data_array;
//
mySDKclass->SDKclassmethod(a_data_array_ptr, b_array_ptr, num, c_data_inst);

but then I get a memory error at run time at the final line in the above code and my assumption is that this is because the function doesn't have initialised memory to write to. Is this a reasonable assumption? I am not entirely confident about my intialisation of a_data_array_ptr but the compiler at least seems happy with this.

I can say what the length of both arrays are. I have tried various combinations of [] and * e.g.:

#define MAXPATHLEN 1024;
int numFtrs;
char b_array[][], ***b_array_ptr;
//code where a value is given to numFtrs - I know this works fine
b_array = new char[MAXPATHLEN][numFtrs];
b_array_ptr = &b_array;

But I get various messages about not being able to convert from char[] to char* and also not being able to set array bounds with non-constants. All of these I understand but it leaves me flummoxed as to how I initialise this char*** variable. Somehow I need to be able to set the sizes of the two arrays.

Please can somebody suggest a solution? If I send a question the software vendor its usually several months before I get some sort of answer.

You should be able to do something like this:

char **b_array;
b_array = new char*[MAXPATHLEN];
for(int i = 0; i < MAXPATHLEN; i++)
	b_array[i] = new char[numFtrs];

char ***b_array_ptr;
b_array_ptr = &b_array;

I am certain there is some shortcut for this, but I don't have time to look around right now.

>>char*** b_array_ptr

You can think this as a pointer to a 2D array of chars. Example will suffice:

#include <iostream>
using namespace std;

int main(){
 char ***ptr = 0;
 //dynamically initialize it
 const int WIDTH = 3;
 const int HEIGHT = 3;
 const int DEPTH = 3;
 
 ptr = new char**[DEPTH];

 //allocate memory
 for(int i = 0; i < DEPTH; ++i){
    ptr[i] = new char*[HEIGHT];
 }
 for(int j = 0; j < DEPTH; ++j){
   for(int k = 0; k < HEIGHT; ++k){
      ptr[j][k] = new char[WIDTH];
    }
  }

 //populate it
 for(int i = 0; i < DEPTH; ++i){
   for(int j = 0; j < HEIGHT; ++j){
     for(int k = 0; k < WIDTH; ++k){
          ptr[i][j][k] = 'A' + (i * j * k) % 27;
     }
   }
 }

  //print it
  for(int i = 0; i < DEPTH; ++i){
   for(int j = 0; j < HEIGHT; ++j){
     for(int k = 0; k < WIDTH; ++k){
          cout << ptr[i][j][k] << " ";
     }
     cout << endl;
    }
   cout << endl;
  }
 
 //deallocate it
  for(int i = 0; i < DEPTH; ++i){
   for(int j = 0; j < HEIGHT; ++j){
     delete [] ptr[i][j];
   }
    delete [] ptr[i];
  }
  delete [] ptr;
  return 0; 
}
Comments
Thank you for this! I understood the fact that char*** is a pointer to 2D array of chars but I struggled to allocate memory for all 3 dimensions. This comment has been of great help.

>> I believe it is a pointer to an array of char arrays.


Let's see. The address of the first element of a char array would be a char*. The address of the first element of an ARRAY of char arrays would likely be a char**. A pointer to THAT might be a char***, so your theory seems reasonable.


I imagine the key would be to look at this function:

mySDKclass->SDKclassmethod(a_data_array_ptr, b_array_ptr, num, c_data_inst);

See what it does and see what it's looking for for the second parameter. In particular, see whether b_array_ptr is an input to the function or an output. If it's an OUTPUT, quite possibly no initialization is required and it's initialized inside the function.

As to how to initialize an array of char arrays pointed to by a char***, that's going to depend on what needs to be initialized and how. If the 2D array is contiguous, it might be something like this.

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

int main()
{
    char array[5][5];
    char*** b_array_ptr;
    *b_array_ptr = (char**) array;
    memset(*b_array_ptr, 'a', sizeof(array));

    printf("Addresses --> %p %p %p %p\n", b_array_ptr, *b_array_ptr, &array, array);


    // test it
    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j < 5; j++)
        {
            cout << array[i][j] << '\t';
        }

        cout << "\n";
    }
    return 0;
}

Brilliant, that works nmaillet, thank you. I should have thought of looping!

Edited 5 Years Ago by IMJS: n/a

I'd like to know why u allocated memory in the order of DEPTH,HEIGHT, WIDTH? is there a specific reason or did u just choose to do it that way? I'll also play around with your code and see if the same end result will be achieved if the order of memory allocation was switched.

>>char*** b_array_ptr

You can think this as a pointer to a 2D array of chars. Example will suffice:

#include <iostream>
using namespace std;

int main(){
 char ***ptr = 0;
 //dynamically initialize it
 const int WIDTH = 3;
 const int HEIGHT = 3;
 const int DEPTH = 3;
 
 ptr = new char**[DEPTH];

 //allocate memory
 for(int i = 0; i < DEPTH; ++i){
    ptr[i] = new char*[HEIGHT];
 }
 for(int j = 0; j < DEPTH; ++j){
   for(int k = 0; k < HEIGHT; ++k){
      ptr[j][k] = new char[WIDTH];
    }
  }

 //populate it
 for(int i = 0; i < DEPTH; ++i){
   for(int j = 0; j < HEIGHT; ++j){
     for(int k = 0; k < WIDTH; ++k){
          ptr[i][j][k] = 'A' + (i * j * k) % 27;
     }
   }
 }

  //print it
  for(int i = 0; i < DEPTH; ++i){
   for(int j = 0; j < HEIGHT; ++j){
     for(int k = 0; k < WIDTH; ++k){
          cout << ptr[i][j][k] << " ";
     }
     cout << endl;
    }
   cout << endl;
  }
 
 //deallocate it
  for(int i = 0; i < DEPTH; ++i){
   for(int j = 0; j < HEIGHT; ++j){
     delete [] ptr[i][j];
   }
    delete [] ptr[i];
  }
  delete [] ptr;
  return 0; 
}
This question has already been answered. Start a new discussion instead.