Domanda

After discovering, that there are no templates in C, I decided to use pointer array in my quest to create dynamic array on my own.

I decided that this answer might be a good start, however, it only considers integer array, which does not suit my needs completely. For that I decided to change it to a void array.

My structure currently looks like this:

typedef struct {
  void *array;
  size_t length;  //How many spaces in array are occupied at the moment
  size_t size;    //How many spaces were allocated
  size_t elm_size;//How large one member of the array is
} Array;

My concern is, how to set the elements of such array. I plan to get them using my function array_get. The matter is, that variable[n] operator makes no sense for the void array, since this operator means *(variable + sizeof(variable)*n) and for void, size is zero. At this point you'd agree that following would be a legitimate way to retrieve an element:

void* array_get(Array *a, size_t offset) {
  if(offset>=a->used) {
    println("Error: access of undefined offset in array.");
    exit(1);
  }
  return void* (((char*)array) + offset*a->elm_size);
}

In program then:

int retrieved_value;
retrieved_value = *((int*)array_get(&my_array, 2)); //The outer star is for dereferencing

However, on setting the elements, I'm helpless.

Please do not think I plan on setting the values at random. I'm aware that a memory must be allocated first.

As I side question for those who like to give those perfect answers that sometimes appear here on SO, I'd like to ask how would I make a function to push a member to an array. Again, void would cause a lot of trouble here, see:

void array_push(Array *a, void* element) {
  if (a->used == a->size) {
    a->size *= 2;
    a->array = (int *)realloc(a->array, a->size * sizeof(int));
  }
  /*array set expression*/ = *(element); //Error! Can't dereference void pointer. Size unknown!
}

But there must be a void* argument for the size of array member is to be decided in the runtime. So I wonder how to cast void* to var_of_sizex*. At that point, I'd apply Array.elm_size, but I'm not aware of such flexible variable type.

È stato utile?

Soluzione

void array_set(Array *a, size_t offset, void* new_value) {
    if (offset >= a->size) {
        fprintf(stderr, "Error: assigning beyond end of array.\n");
        exit(1);
    }
    memcpy(((char*)(a->array)) + offset*a->elm_size, new_value, a->elm_size);
}

Depending on how you want to do things, you might want to move the realloc logic from array_push to array_set. So array_set would automatically grow the array rather than report an error when you try to write beyond the end.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top