2

I'm trying to build a char array for storing the return value of a function. In the following function the data is stored in *****valv**. How to build a extern variable to access the data?

int credis_lrange(REDIS rhnd, const char *key, 
                   int start, int end, char ***valv) 
{
  int rc;

  if ((rc = cr_sendfandreceive(rhnd, CR_MULTIBULK, "LRANGE %s %d %d\r\n", 
                                key, start, end)) == 0) 
  {
    *valv = rhnd->reply.multibulk.bulks;
    rc = rhnd->reply.multibulk.len;
  }

  return rc;
}

Solution:

char **elements;

int size = credis_lrange(this->redis,"object_2",600,603,&elements);

for (int i=0; i<size;i++) {
    cout << "element: " << elements[i] << endl; 
}

Thanks to everyone!

dan
  • 5,377
  • 13
  • 39
  • 44
  • 1
    Many duplicates. Start with http://stackoverflow.com/questions/917783/how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c http://stackoverflow.com/questions/1874604/passing-an-array-of-arrays-in-c http://stackoverflow.com/questions/2003745/pointer-address-in-a-c-multidimensional-array and there are others... – dmckee --- ex-moderator kitten Feb 02 '10 at 23:52
  • Not that it directly answers your question, but arrays are "non-preferred" in C++ and you should be using an STL container class, probably vector. – Mawg says reinstate Monica Feb 03 '10 at 00:10
  • The credis lib is a C lib. Can I use C++ vectors in C? – dan Feb 03 '10 at 00:18
  • not in any reliable way...if you understood how the `std::vector` was implemented on that compiler/machine/library combo you could theoretically do something, but it is not worth it. – dmckee --- ex-moderator kitten Feb 03 '10 at 00:53

3 Answers3

5
char ***element[size];

Is not exactly a 3D array, but an array of size elements of pointers-to-pointers-to-pointers to char.

Use any one of the following:

char e[ D1 ][ D2 ][ D3 ]; /* D1, D2, D3 are integral constants */
char *e[ D2 ][ D3 ];
char e[][ D2 ][ D3 ];

Also, you can pass it on by simply speficying e as the argument to your function.

On further reading, it appears that the parameter is not really a 3D array but a pointer to an array of C-style strings. Note, the syntax may be the same, the intent is different.

In that case, you'll need to do two things:

  • Specify the number of strings you want to store in the array
  • For each string
    • Allocate memory
    • Copy string data to the char array

And finally, you'll be passing in the address of this array of strings on to the credis_lrange function.

dirkgently
  • 108,024
  • 16
  • 131
  • 187
  • Hi Dirk, thanks for your super fast reply. So I have to make 3 for loops and allocate memory for each element per array level? – dan Feb 02 '10 at 23:38
  • If you use Dirks first suggestion, you don't need to do any memory allocation. That's all allocated in one contiguous lump. Although when you use "e" it will act a lot like a pointer (to a pointer to a pointer to a char), that doesn't imply a need to allocate/free memory from the heap. –  Feb 02 '10 at 23:53
  • In Dirk's first example you don't need to allocate memory. In the 2nd example you need to loop through once and allocate memory. – Jagannath Feb 02 '10 at 23:55
  • I've tried Dirks first suggestion but getting this error: cannot convert 'char (*)[1024][1024]' to 'char***' for argument '5' to 'int credis_lrange(_cr_redis*, const char*, int, int, char***)' – dan Feb 03 '10 at 00:07
  • @dirk: thanks again for your help. I'm getting almost the same error: cannot convert 'char ( * )[1024][1024][1024]' to 'char***' for argument '5' to 'int credis_lrange(_cr_redis*, const char*, int, int, char***)' – dan Feb 03 '10 at 00:43
  • @dan: You need to use `&e[ 0 ][ 0 ][ 0 ]` if you are using the first alternative. – dirkgently Feb 03 '10 at 00:47
0

I only found one hit on Google for this, but it looks like the cr_sendfandreceive function allocates its rhnd->reply.multibulk.bulks member, so you don't actually have to pass it back (since you were passed rhnd in the first place).

If you want to copy it, then you would declare elements as a char** and pass its address (or use references), and then inside the method you would clone the bulks member and also each string in the array (in a loop).

Neil
  • 54,642
  • 8
  • 60
  • 72
  • Hi Neil, thanks for your reply. Could you give any sample code on this? – dan Feb 02 '10 at 23:59
  • This is the basic idea, but obviously without any error checking: char** clone(int argc, char **argv) { char** result = (char**)malloc(argc * sizeof(char*)); while (argc--) result[argc] = strdup(argv[argc]); return result; } – Neil Feb 16 '10 at 00:27
0

In Arduino Studio environment, for MCUs programming like ST or ESP32 using PSRAM, one can allocate dynamic memory for a 3D multiarray of char array, sized 255, like so:

char*** 3d_array = (char***) heap_caps_malloc( sizeof(char)*255*(size_x*size_y*size_z), MALLOC_CAP_SPIRAM);

for X86/ X64 architectures a 3D multiaaray of char array, sized 255 can be declared as follows:

char*** 3d_array = (char***) malloc( sizeof(char)*255*(size_x*size_y*size_z));
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Miguel Tomás
  • 1,714
  • 1
  • 13
  • 23