Assigning an address to a struct pointer array member in C

穿精又带淫゛_ 提交于 2019-12-06 05:49:11
Jerry Coffin

Based on your description, you're starting off wrong, so by the time you get to copying things, nothing you can do is likely to work.

Right now, you've defined new_array (and, presumably, array) as a pointer to obj. The result looks like this:

In this case, you have a pointer to a dynamically allocated array of objects. When/if you expand the allocation, you'll need to copy all the objects themselves.

According to your description: "(i.e. arrays of pointers to heap structs)", what you want is an array of pointers. If you want to allocate that array of pointers automatically, your definition would look like:

obj *array[NUMBER];

My guess is that's not what you want though. Presumably, you want to allocate that array dynamically as well. That would look like this:

In this case, new_array and array will each need to be defined as a pointer to pointer to obj. You'd then allocate an array of pointers (i.e., pointers to as many objs as you want) and have each point point at an obj:

obj **new_array;

// allocate an array of pointers with space to point at more items:    
new_array = malloc(sizeof(obj *) * new_elements);

// copy the pointers to the current items to the new array:
for (i=0; i<current_elements; i++)
    new_array[i] = array[i];

The advantage of this is that when you do the copying, you only copy pointers, not the objects themselves. Especially with large objects, this can save a substantial amount of effort. The tradeoff is that using an element goes through two levels of indirection intead of one, so the reference may be slower (though rarely much slower, especially on a relatively high-performance processor).

As @rerun already pointed out, in either case you probably want to use realloc. In particular, this might be able to expand an allocation "in place", and avoid copying data as often. Of course, that's not guaranteed, but at least you're giving it a chance; if you malloc and copy every time, you eliminate even the possibility of that optimization.

You have two arrays doesn't new_array[i] = array[i] do what you need.

  • Have you looked at realloc as a possible solution.

Just assign the values across. new_array[i] = array[i].

The problem you may be running into is that, for obj* to actually be an array of pointers, obj must itself be a pointer type:

typedef struct
{
  int value1;
} obj_pool;

typedef obj_pool* obj;

int main(int argc, char* argv[])
{
  obj_pool pool1;
  pool1.value1 = 5;
  obj array[] = { &pool1 };
  array[0]->value1 = 16;
  return 0;
}

Another problem you'll run into once you get this compiling is that sizeof(array) == sizeof(obj*). NUM_ELEM(array) will always return the same value. This means you'll have to pass a size_t array_size parameter to your function.

in your code elements of the array are not pointers on the structure, they are structure objects. elements of the this array obj** array are pointers on the structure obj.

#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))

void add_to_obj_array(obj* new_obj, obj** array)
{
  int number_of_elements = 0;
  if (array != NULL)
  {
    number_of_elements = NUM_ELEM(array);
  }

  // expand array with one more item
  array = (obj**)realloc(array, (number_of_elements + 1) * sizeof(new_obj));

  if (array == NULL )
  {
    /* memory request refused :( */
    return;
  }

  // Put new item at the last place on the array
  array[number_of_elements] = new_obj;
}

So here we used matrix (pointer on pointers of the obj structure). When we add new element we simply expand existing array for one place and on that place we put new structure object. There is no need to return value because we operate on the pointers of the objects, and all change is done on actual objects, not on their copies.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!