【发布时间】:2017-12-26 17:04:08
【问题描述】:
我正在使用 realloc 来调整包含 3 个点 x、y 和 z 的结构数组的大小。这个结构被封装在另一个结构中,该结构包含数组、数组的长度和一个“保留”值,当很明显更多的点结构将附加到结构数组。
我正在使用如下所示的 Makefile 进行编译:
CFLAGS = -g -Wall
LIBS = -lm
default: echo "You must specify a target, e.g. file1, file2"
file2:
gcc $(CFLAGS) -o $@ test.c file2.c $(LIBS)
我有一个函数来初始化一个空数组结构,一个将数组重置为空并释放任何动态分配的内存,一个将一个点附加到数组的末尾,一个删除一个由索引指定的点价值。
我遇到了两个我找不到原因的错误。一个是我的代码返回一个非零状态码 1,另一个是当我附加几千个点时长度似乎减一。
我让 append 函数完成所有工作,但如果我应该在初始化时分配动态内存,请告诉我。我很确定我的重置和删除功能正在按预期工作。请看一下追加。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <assert.h>
typedef struct point
{
int x, y, z;
} point_t;
typedef struct
{
// number of points in the array
size_t len;
// pointer to an array of point_t structs
point_t* points;
size_t reserved;
} point_array_t;
void point_array_initial( point_array_t* pa )
{
assert(pa);
pa->len = 0;
pa->reserved = 0;
pa->points=NULL;
}
void point_array_reset( point_array_t* pa )
{//just free the array and set pa to NULL
assert(pa);
pa->points = memset(pa->points, 0, sizeof(point_t)*(pa->len));
pa->len = 0;
pa->reserved=0;
free(pa->points);
pa->points=NULL;
}
int point_array_append( point_array_t* pa, point_t* p )
{
assert(pa);
assert(p);
if(pa == NULL)//something wrong with intialization or reset
{
return 1;
}
if(p == NULL)//nothing to append
{
return 1;
}
//append the first point
if(pa->len == 0)
{
pa->len=1;
pa->reserved=pa->len*2;
pa->points = malloc(sizeof(point_t)* (pa->reserved));
if(pa->points == NULL)//malloc failed
{
return 1;
}
pa->points[pa->len-1].x = p->x;
pa->points[pa->len-1].y = p->y;
pa->points[pa->len-1].z = p->z;
}
if (pa->reserved > pa->len )
{
pa->len+=1;
pa->points[pa->len-1].x = p->x;//insert at index 0
pa->points[pa->len-1].y = p->y;
pa->points[pa->len-1].z = p->z;
}
//when we run out of space in reserved (len has caught up)
else if(pa->reserved == pa->len)
{
pa->len+=1;
pa->reserved=pa->len*2;
pa->points=realloc(pa->points, sizeof(point_t)*(pa->reserved));//doubling size of array
pa->points[pa->len-1].x = p->x;//TODO: change formula to find insertion point
pa->points[pa->len-1].y = p->y;
pa->points[pa->len-1].z = p->z;
}
return 0;
}
int point_array_remove( point_array_t* pa, unsigned int i )
{
assert(pa);
if (i >= pa->len)//out of bounds
{
return 1;
}
if(pa->len==0)//0 elements trying to remove from empty array
{
//pa->len=0;
//free(pa->points);
//pa->points=NULL;
return 1;
}
else if(pa->len ==1)//remove only element
{
pa->len-=1;//no copying required, just shorten
pa->points=realloc(pa->points, sizeof(point_t)*(pa->len));
//free(pa->points);
//pa->points=NULL;
}
else//array size is longer than 1 or 0
{
pa->points[i].x = pa->points[pa->len-1].x;
pa->points[i].y = pa->points[pa->len-1].y;
pa->points[i].z = pa->points[pa->len-1].z;
pa->len-= 1;//shorten array size
pa->reserved = pa->len*2;
pa->points=realloc(pa->points, sizeof(point_t)*(pa->len));//could reallocate for reserve here to increase speed.
}
return 0;
}
【问题讨论】:
-
只需编码
memset(pa->points, 0, sizeof(point_t)*(pa->len));而不分配memset的(无用)结果 -
据我所知,重置函数中的
memset行毫无意义。摆脱它。而且数学肯定比你在代码的其他各个部分中做的更简单。 -
调试器很吓人。 . . 所以用一些你知道很好的简单代码来感受一下,你可以引入故意的错误。永远不要试图同时解决两个问题。
-
pa->len-=1;//no copying required, just shorten pa->points=realloc(pa->points, sizeof(point_t)*(pa->len));:需要更改pa->reserved。 -
@CraigEstey,我不是 100% 清楚“失败”的含义,但在该案例代码的末尾添加了一个
return 0;。
标签: c dynamic structure realloc