4

ですから、私はC#の人で、Cの学習に取り組んでいます。最初の(個人的な)プロジェクトとして、基本的な座標ジオメトリライブラリを作成しようとしています。

質問:ライブラリをターゲットにしているプログラマーにメモリを割り当てるのではなく、バックグラウンドでヒープにメモリを割り当てるのがCプログラミングのベストプラクティスですか?

たとえば、私の「ポイント」構造体と関連メソッド:

point.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);

point.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'を作成していることに注意してください(正直なところ、このプロジェクトは私と学習のためだけのものです...)。これは悪い習慣ですか?ユーザーに特定の方法でプログラミングを強いているような気がします。同じことがmidpoint()メソッドにも当てはまります。ここでも、「ポイント」構造体へのポインタを使用する必要があります。

SOでのCライブラリの設計に関する正確な質問を見つけることができませんでしたが、該当する場合は正しい方向に向けてください。

ありがとう。

4

2 に答える 2

6

本当に好みです。私は通常、ユーザーがオブジェクトにメモリを好きなように割り当ててから、メンバーを初期化できるようにすることをサブスクライブします。

/* 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], ...);
}

編集:

Opaque Pointer戦略を使用して構造体のメンバーをライブラリユーザーから非表示にする場合は、説明した方法を使用してそれらのメンバーにメモリを割り当てる必要があります。これは、ライブラリに構造を割り当てるための大きなメリットです。

于 2012-04-09T18:47:31.757 に答える
3

ベストプラクティスは、Cの長所であるため、プログラマーが最速で実行できるようにライブラリをコーディングすることです。たとえば、プログラマーは、これらのポイント構造体が何万も必要になることを知っている場合があります。将来のアクセスをローカルに保つことは、メモリの1つのブロックにすべての構造体を割り当てることを好むかもしれません。ライブラリでプログラマーが構造体を初期化するためのポインターを渡すことができる場合、プログラマーはこれを行うことができます。しかし、あなたが彼のために記憶を割り当てることを主張するならば、彼はそうすることができません。

于 2012-04-09T18:49:53.010 に答える