4

構造体へのポインターのアドレスを関数に渡す必要があります。これにより、構造体の配列にメモリが動的に割り当てられ、値が入力されます。

呼び出しメソッドから、func1 から戻ると、構造体の配列を反復処理して、構造体変数の値を表示できるはずです。

動的に作成された構造体の配列を繰り返し処理しながら、ポインターのアドレスを構造体に渡す方法を誰かが説明できますか?

私のサンプルコードは次のようになります:

struct test {
    int a;
    int b;
};

void func1(int *n,struct test **testobj)

{
    n=5;
    *testobj = (struct test*) malloc(n*sizeof(struct test));
    for(i=0;i<n;i++)
    {
        (*testobj)[i].a=1;
        (*testobj)[i].b=2;
    }
}

int main()
{
    struct test testobj;int n;
    func1(&n,&testobj);
    for(i=0;i<n;i++)
    {
        printf("%d %d",(*testobj)[i].a,*testobj)[i].b);
    }
    free(testobj);
}
4

4 に答える 4

3

testmain() で、構造体へのポインターを定義します。

struct test *testPtr;

そのポインターのアドレスを取得するには、アドレス&演算子を使用します。

&testPtr;

これはポインタのアドレスを返し、型を持ちますstruct test **

次に、これを function に渡すことができます。これによりfunc1、正しい割り当てが行われます (キャストmalloc()は一般的に悪い習慣と見なされますが、 malloc の結果をキャストしますか? )。それ以外func1()は良さそうです... ライン...

*testobj = malloc(n*sizeof(struct test));

... 正しい。*testobjを実行して取得した二重ポインタを逆参照し&testPtr、新しいメモリのアドレスをポインタに格納します。インデックスを取得する前に、逆参照をブラケットで囲む必要があるよりも優先順位が高い(*testobj)[i]ため、ダブルポインターを逆参照する場合も正しいです。[]*

したがって、func1()ポインタtestPtrが返されると、割り当てた構造体の配列を指すようになり、etcn testを使用してアクセスできるようになります。testPtr[i].a

編集: for ループは次のようになります。

for(i=0;i<n;i++)
    printf("%d %d", testobj[i].a, testobj[i].b);

元の for ループでコンパイル エラーが発生したはずですか? 元のコードtestobjではポインターではないため、逆参照することはできません。

したがって、要約の答えは、ポインターとしてmain()宣言し、配列要素に次のようにアクセスすることです:)testobjtestobj[n]

編集:エリックが指摘したように、から削除n=5;func1()ます。*n=5おそらくある種のデバッグ手順を意味していたと思います...おそらくn、構造体配列に必要なオブジェクトの数を関数への入力として使用することを意味しています。初期化するnか、おそらく再定義func1()して

void func1(int n,struct test **testobj) // n is no longer a poitner, just a number
于 2013-06-25T12:57:58.627 に答える
0

あなたのコードは私にはほとんど問題ないように見えます。それをうまくする唯一の編集は--

代わりに

struct test testobj;

次のコードを入れます

struct test  *testobj;

残りはそのままで…!

これが必要なものの作業バージョンです。ここでは、必要に応じて、呼び出された関数にメモリが割り当てられます

#include <stdlib.h>
#include <stdio.h>
struct tests {
    int a;
    int b;
};

void func1(int *n,struct tests **testobj)

{
    int i;
    *n=5;
    *testobj = (struct tests*) malloc((*n)*sizeof(struct tests));
    for(i=0;i<(*n);i++)
    {
        (*testobj)[i].a=1;
        (*testobj)[i].b=2;
    }
}

int main()
{
    int i;
    struct tests *testobj;int n;
    func1(&n,&testobj);
    for(i=0;i<(n);i++)
    {
        printf("%d %d",(testobj)[i].a,testobj[i].b);
    }
    free(testobj);
}
于 2013-06-25T13:02:22.103 に答える
0

あなたが求めているバージョンは完全には明らかではありませんが、次のいずれかがそれをカバーするはずです:

/* allocate some number of tests.
 *
 * out_n: out parameter with array count
 * returns: an array of tests
 */
struct test* allocate_some_tests(int *out_n) {
    int n = 5; /* hardcoded, random or otherwise unknown to caller */
    *out_n = n
    struct test *t = malloc(n * sizeof(*t));
    while (n--) {
        t[n].a = 1;
        t[n].b = 2;
    }
    return t;
}

/* allocate a specific number of tests.
 *
 * n: in parameter with desired array count
 * returns: an array of tests
 */
struct test* allocate_n_tests(int n) {
    struct test *t = malloc(n * sizeof(*t));
    while (n--) {
        t[n].a = 1;
        t[n].b = 2;
    }
    return t;
}

割り当てられた配列を返すだけでよいことに注意してください。ここではポインタからポインタへのポインタは必要ありません。

それらを呼び出し、結果を反復処理する場合:

void print_tests(struct test *t, int n) {
    for (; n--; t++)
        printf("{%d, %d}\n", t->a, t->b);
}

int main()
{
    int count1; /* I don't know how many yet */
    struct test *array1 = allocate_some_tests(&count1);
    print_tests(array1, count1);

    int count2 = 3; /* I choose the number */
    struct test *array2 = allocate_n_tests(count2);
    print_tests(array2, count2);
}
于 2013-06-25T13:16:49.167 に答える