C库设计-结构和内存管理[最佳实践]

C库设计-结构和内存管理[最佳实践],c,memory,struct,C,Memory,Struct,因此,我是一个C#家伙,正在尝试学习C。作为第一个(个人)项目,我正在尝试编写一个基本的坐标几何库 问题:最好的C编程实践是在后台在堆上分配内存,而不是让以库为目标的程序员这样做吗 例如,我的“点”结构和相关方法: 点h /* A basic point type. */ typedef struct point { float x; float y; float z; char *note; }point; /* Initializes a basic poi

因此,我是一个C#家伙,正在尝试学习C。作为第一个(个人)项目,我正在尝试编写一个基本的坐标几何库

问题:最好的C编程实践是在后台在堆上分配内存,而不是让以库为目标的程序员这样做吗

例如,我的“点”结构和相关方法:

点h

/* A basic point type. */
typedef struct point
{
    float x;
    float y;
    float z;
    char *note;
}point;

/* Initializes a basic point type. [Free with free_point method] */
point *create_point(float pos_x, float pos_y, float pos_z, char *_note);
/* Frees a point type. */
void free_point(point *_point);
/* Finds the midpoint between two points. */
point *midpoint(point *pt1, point *pt2);
点c

#include "point.h"

/* Initializes a basic point type. [Free with free_point method] */
point *create_point(float pos_x, float pos_y, float pos_z, char *_note)
{
    point *p;
    size_t notelen = strlen(_note);

    p = (point*)malloc(sizeof(point));
    p->x = pos_x;
    p->y = pos_y;
    p->z = pos_z;

    p->note = (char*)calloc(notelen + 1, sizeof(char));
    strcpy_s(p->note, notelen + 1, _note);

    return p;

}
/* Frees a point type. */
void free_point(point *_point)
{
    free (_point->note);
    free (_point);
}

/* Creates a midpoint between two points. */
point *midpoint(point *pt1, point *pt2)
{
    float mid_x = (pt1->x + pt2->x) * 0.5f;
    float mid_y = (pt1->y + pt2->y) * 0.5f;
    float mid_z = (pt1->z + pt2->z) * 0.5f;

    point *p = create_point(mid_x, mid_y, mid_z, "Midpoint");
    return p;
}
请注意,我通过create_point()方法在堆上为实现/使用我的lib的人创建结构“point”(老实说,这个项目只是为了我和学习…)。这是一种糟糕的做法吗?感觉上我是在强迫用户以某种方式编程。中点()方法也是如此。同样,必须使用指向“点”结构的指针

我找不到关于C库设计的确切问题,但是如果适用,请给我指出正确的方向


谢谢。

这是我的首选,真的。我通常订阅让用户根据自己的意愿为对象分配内存,然后为他们初始化成员

/* here a non-zero return value might indicate if for example
 * we failed to allocate memory for note */
int point_init(struct point* p, int x, int y, char* note)
{
  /* ... */
}

/* usage: */
struct point p;
if (point_init(&p, 1, 2, "hello")) {
  /* error */
}
这使用户可以选择分配内存中相邻的点数组,而不是跟踪指向点的指针数组:

struct point mypoints[NUM_POINTS];

for(size_t i = 0; i < NUM_POINTS; ++i) {
  point_init(&mypoints[i], ...);
}
struct point mypoints[NUM_POINTS];
对于(大小i=0;i
编辑:
如果要使用该策略向库用户隐藏结构的成员,则需要使用所描述的方法为它们分配内存。这对于在库中分配结构来说无疑是一个巨大的好处。

最佳实践是以程序员能够以最快的速度编写库,因为这是C的一个优点。例如,程序员可能知道需要成千上万个这样的点结构,为了保证将来的访问是本地的,他们可能更愿意在一块内存中分配所有的结构。如果您的库允许程序员为要初始化的结构传递指针,那么他可以这样做。但是如果您坚持要为他分配内存,他就不能。

作为旁注,我确信存在一些常见的编码错误(即返回malloc()所在的指针)失败。我知道这需要修正。对此没有明确的答案。我个人的偏好是尽可能多地封装,但其他人的观点可能会有所不同。@OliCharlesworth这也是我的观点,我认为如果一个库更易于使用并尽可能多地管理其内部内容,它会更好。@JTA:不要抛出retu
malloc
void*
的rn值与任何指针类型兼容。