tags:

views:

102

answers:

3

A function I need to use requires a vector argument for return storage with the following signature:

char ***vvar

What am I supposed to pass in there? How do I access elements afterward?

A: 

This is not a vector by the looks of it.

If the function signature is somethings like function(...,char ***vvar,...), then your solution is not simple.

You need to know how much buffer space you need in each dimension, then create the complicated array as follows:

int dim_1 = 5, dim_2 = 4, dim_3 = 10;
char ***buffer = malloc(sizeof(char**)*dim_1);
for (int i=0;i++;i<dim_1) {
  char **buffer_2 = malloc(sizeof(char*)*dim_2);
  for (int j=0;j++;j<dim_2) {
    char *buffer_3 = malloc(dim_3);
    buffer_2[j] = buffer_3;
  }
  buffer[i] = buffer_2;
}
Alexander Rafferty
This is C++ code, not C
Bart van Ingen Schenau
@Alexander Rafferty: And what **C** header do you include for the `new` operator?
Praetorian
I am very used to using the new operator, and if anyone would like to just change it to malloc that's fine. I don't understand why people are still using C (just my opinion).
Alexander Rafferty
@Alexander-Rafferty: because it's powerful and you can do bad things with it.
David
And C++ isn't?.
Alexander Rafferty
@Alexander: People still use C because either they have a lot of legacy code in C or because they work on a platform that does not have a C++ compiler,or just because they like C better.
Bart van Ingen Schenau
+1  A: 

Let's say you want a function that creates a vector of strings. You might define it and call it like this:

#include "stdio.h"
#include "stdlib.h"

void make_vector(char*** vvar)
{
   /* We're going to create a vector of strings. */
   char** vector = malloc(sizeof(char*) * 3 );
   vector[0] = "Hello";
   vector[1] = "world!";
   vector[2] = NULL;

   /* Now we give the address of our vector to the caller. */
   *vvar = vector;
}

int main(void)
{
   char** vector_of_strings = NULL;
   make_vector(&vector_of_strings);
   printf("%s\n", vector_of_strings[0]);
   return 0;  /* Memory leak is an exercise for the reader. :-) */
}

(In this example it would be simpler to have make_vector return the array, but in a more complex example it's reasonable to pass the address of vector_of_strings.)

RichieHindle
Is it really necessary to cast malloc return value?
Nyan
@Nyan: No, not in C, you're quite right. Now fixed. (I spend too much time mixing C and C++ :-)
RichieHindle
A: 

I will assume that the vector will contain strings, as that makes the most sense with the signature you describe. As you also did not give any code, I will assume the function you need to call looks similar to this:

/* This function creates a vector with room for 'length' strings and places it in 'vvar' */
void create_string_vector(int /* in */ length, char*** /* out */ vvar);

As the function expects to be able to change vvar and have that change reflected in the caller, you must pass the address of some variable, so the call should look like

create_string_vector(my_length, &my_var);

That takes care of one level of pointers.
This leaves just the question of how to declare my_var. As it will be a vector, or array, of unknown size, you need to declare it as a pointer. And a string is also a kind of array of unknown size of characters, so you need a pointer for that as well. This leads to the declaration

char* *my_var;

Element access is the easy part: You can treat my_var just as an array:

my_var[0] = "Hello";
Bart van Ingen Schenau