在C中为结构指针数组成员分配地址

一些指针算术有相当大的麻烦。 我我得到了概念(指针变量指向内存地址,正常变量指向数据)但我相信我的问题是语法( *, &, (*), *(),等)

我想要做的是构建一个自定义结构的动态数组(即指向堆结构的指针数组),我的界面提供了两个方法,“ad_to_obj_array”(它将对象添加,而数组可以为null为空)和“obj_array_dustbin”(它只是处理数组,也处理内容,堆objs)。 前者呈现如下。

对象的细节并不重要(并且结构已经重命名)但是我对一般问题的解决方案如下,如果您能发现错误,我将不胜感激。 编译器抱怨无效的左值,我尝试将RHS上的指针中的地址分配给堆结构指针数组中的指针值:

 #define NUM_ELEM(x) (sizeof (x) / sizeof (*(x))) obj* add_to_obj_array(obj* new_obj, obj* array) { int number_of_elements = 0; if (array != NULL) { number_of_elements = NUM_ELEM(array); } obj* new_array = NULL; /* note: I am expecting sizeof(new_obj) to return the size of an obj* to go into the array of pointers. */ if ( NULL == (new_array = (obj*)malloc((number_of_elements + 1)* sizeof(new_obj))) ) { /* memory request refused :( */ return NULL; } /* copy the old array pointers into the new array's pointer slots: */ int i; for (i = 0; i  0) { free(&array); } return new_array; } 

现在,我尝试了以下违规行的排列:

  &(new_array[i]) = &(array[i]); *(new_array[i]) = &(array[i]); new_array[i] = &(array[i]); 

并且都给出了一种或另一种编译器错误。 我很确定右侧是旧数组的第i个元素的地址,但是当数组的元素是指向结构的指针时,如何分配给new的第i个元素?

编辑 – 请注意,上面的宏NUM_ELEM不工作; 它将永远返回1.请参阅@Merlyn Morgan-Graham的答案,了解原因。

根据你的描述,你开始错了,所以当你复制东西时,你所做的一切都可能起作用。

现在,您已将new_array (可能是array )定义为obj的指针。 结果如下:

替代文字

在这种情况下,您有一个指向动态分配的对象数组的指针。 当/如果扩展分配时,您需要自己复制所有对象。

根据你的描述:“(即指向堆结构的指针数组)”,你想要的是一个指针数组。 如果要自动分配该指针数组,您的定义将如下所示:

 obj *array[NUMBER]; 

我的猜测是,这不是你想要的。 据推测,您也希望动态分配该数组。 这看起来像这样:

替代文字

在这种情况下, new_arrayarray都需要定义为指向obj指针。 然后你可以分配一个指针数组(即指向你想要的obj的指针)并将每个指针指向一个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 

这样做的好处是,当您进行复制时,您只复制指针 ,而不是对象本身。 特别是对于大型物体,这可以节省大量的精力。 权衡是使用一个元素经过两个级别的间接intead为1,因此引用可能更慢(尽管很少慢,特别是在相对高性能的处理器上)。

正如@rerun已经指出的那样,在任何一种情况下你都可能想要使用realloc 。 特别是,这可能能够“就地”扩展分配,并避免经常复制数据。 当然,这不是保证,但至少你给它一个机会; 如果你每次都进行malloc和复制,你甚至可以消除优化的可能性。

你有两个数组不new_array[i] = array[i]做你需要的。

  • 您是否将realloc视为可能的解决方案?

只需分配值即可。 new_array[i] = array[i]

你可能遇到的问题是,对于obj*实际上是一个指针数组, obj本身必须是一个指针类型:

 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; } 

进行此编译后,您将遇到的另一个问题是sizeof(array) == sizeof(obj*)NUM_ELEM(array)始终返回相同的值。 这意味着您必须将size_t array_size参数传递给您的函数。

在你的代码元素中,数组不是结构上的指针,它们是结构对象。 这个数组obj **数组的元素是结构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; } 

所以这里我们使用了矩阵(指向obj结构的指针)。 当我们添加新元素时,我们只需将现有数组扩展为一个地方,并在那个地方放置新的结构对象。 不需要返回值,因为我们操作对象的指针,所有更改都在实际对象上完成,而不是在副本上完成。