簡體   English   中英

你如何在函數內部使用結構體的malloc?

[英]How do you use malloc of struct inside a function?

在這段代碼中,

#include <stdio.h>
#include <stdlib.h>

typedef struct test
{
  int i;
  double data;
} test;

void add(ar) struct test *ar;
{
  int num = 10;
  // *ar = malloc(num * sizeof(struct test)); // Adding this
  for (int i = 0; i < num; i++)
  {
    ar[i].i = i;
    ar[i].data = i * i;
  }
}

int main(void)
{
  test ar[10]; // Removing this
  add(&ar);

  for (int i = 0; i < 10; i++)
  {
    printf("%d %f\n", ar[i].i, ar[i].data);
  }
  return 0;
}

我們如何在main定義struct但在function分配內存?

我想在函數add設置數字 ( num ),因為它在main還不知道。

有兩個值必須從add()傳回main()nummalloc() ed 數組本身。 由於您只能返回一個值,因此有兩種情況:

a) 返回 num 並有一個test **參數來傳回數組

int add( struct test **ar )
{
   int num = 10;

   *ar = malloc( num * sizeof **ar );
   // initialize everything, you have to replace ar[i] by (*ar)[i]
   return num;
}

叫它

struct test *ar;
int num = add( &ar );

b) 返回數組並有一個int *參數來傳回 num

struct test *add( int *num )
{
   *num = 10;
   
   struct test *ar = malloc( *num * sizeof *ar );
   // initialize everything as you do now
   return ar;
}

叫它

 int num;
 struct test *ar = add( &num );

正如@Bodo 提到的,無論哪種方式,您都必須調用free( ar ); main()當您不再需要ar 您可以直接調用它或考慮使用像free_test( struct test *ar, int num );這樣的清理函數free_test( struct test *ar, int num ); 這樣就可以了。 如果您有更多malloc()為單個結構元素分配內存(例如,如果它們包含用於存儲字符串的char *元素malloc()則此類函數特別有用。

  • 使用參數傳遞參數
  • 使用返回值將東西返回給調用者

#include <stdio.h>
#include <stdlib.h>

struct test
{
  int i;
  double data;
} ;

struct test *test_create(unsigned ntest)
{
  struct test *pp;
  unsigned idx;

  pp = malloc(sizeof *pp * ntest);
  for (idx = 0; idx < ntest; idx++)
  {
    pp[idx].i = idx;
    pp[idx].data = idx * idx;
  }

return pp;
}

int main(void)
{
  struct test *ptr;
  ptr = test_create(10);

  for (int i = 0; i < 10; i++)
  {
    printf("%d %f\n", ptr[i].i, ptr[i].data);
  }
  return 0;
}

更新:如果您想返回多個項目,您可以將這些項目放在一個結構中:


#include <stdio.h>
#include <stdlib.h>

struct dope {
        unsigned size;
        struct {
                int i;
                double data;
                } *array;
        } ;

struct dope *dope_create(void)
{
  struct dope *pp;
  unsigned omg =10;

  pp = malloc(sizeof *pp );
  pp->array = malloc(sizeof *pp->array * omg);
  pp->size = omg;

  for (omg = 0; omg < pp->size; omg++)
  {
    pp->array[omg].i = omg;
    pp->array[omg].data = omg * omg;
  }

return pp;
}

int main(void)
{
  struct dope *ptr;
  ptr = dope_create();

  for (int iii = 0; iii < ptr->size; iii++)
  {
    printf("%d %f\n", ptr->array[iii].i, ptr->array[iii].data);
  }
  return 0;
}

您已經有很好的答案作為替代方案。 無論如何,我將向您展示兩種常見的編寫方式的代碼。

正如我在您的代碼中看到的,工廠函數將確定要分配的結構test的實際數量。 我將在示例中:

  • 使用rand()生成隨機數量的結構體,因為它在這里沒有區別
  • 將它們填入 (1,1.01), (2,2.02) ... 只是為了有一個已知的測試值
  • 在屏幕上顯示結構的內容
  • free() 他們在退出
  • 假設也可以創建 0 個結構

1:使用以NULL結尾的指針序列

因為它在所有 C 字符串中都成功使用了 :) 我們可以在這里使用它。 與字符串(C 字符串)一樣,您需要搜索終止符以獲得數組大小(當然,您可以將第一個指針設置為大小,類似於 Pascal )。 事先知道結構體的數量可能重要,也可能不重要。

Test**      add_vector()
{
    // returns a null terminated array of pointers
    // to 'Test', pointing to actual instances of
    // 'Test', allocated and numbered with 'i' starting
    //  at 1 and 'data' starting at 1.01
    int num = rand() % 10;  // 0 to 9 Test
    fprintf(stderr,
        "add_vector(): creating %d structs\n", num);
    // at least one pointer, the terminating one
    Test** ar = (Test**)malloc((1 + num) * sizeof(Test*));
    int    ix = 0;
    for (ix = 0; ix < num; ix += 1)
    {
        ar[ix] = (Test*)malloc(sizeof(Test));
        // sets up ar[i] to a known value
        ar[ix]->i    = 1 + ix;
        ar[ix]->data = 1 + ix + (1 + ix) / 100.;
    };              // for()
    ar[ix] = NULL;  // the terminator one, as in strings
    return ar;
}

要使用它,您只需調用

    Test** vector = add_vector();

正如您在下面的示例中看到的那樣。 返回單個指針。 不需要爭論。 如果結構數為零,則返回單個指針,就像使用空字符串一樣。

# of structs 在函數內部定義,所有的 structs 實例在返回給調用者之前都被分配和編號。

2:返回一個指向結構體的指針

typedef struct
{
    int    i;
    double data;

}   Test;

typedef struct
{
    unsigned size;
    Test*    test;

} V_Test;

V_Test*     add_struct();      

分配函數返回一個指向V_Test結構的指針,該結構包含一個Test結構數組和一個size元素,每個 C 程序的 in main()

    int main(in argc, char** argv)

這是代碼:

V_Test*     add_struct()
{
    // returns a vector of structs inside V_Test,
    // with known 'size', like in main( int,char**) 
    // The structs are initialized with 'i' starting
    //  at 1 and 'data' starting at 1.01
    unsigned num = rand() % 10;  // 0 to 9 Test
    fprintf(stderr, "add_struct(): creating %d structs\n", num);
    V_Test* v  = (V_Test*) malloc(sizeof(V_Test));
    v->size   = num;
    if (num == 0)
    {
        v->test = NULL;
        return v;
    };
    v->test  = (Test*)malloc(num * sizeof(Test));
    for (unsigned ix = 0; ix < num; ix += 1)
    {
        v->test[ix].i = 1 + ix;
        v->test[ix].data = 1 + ix + (1 + ix) / 100.;
    };              // for()
    return v;
}

要使用它,您只需調用

    V_Test* vector = add_struct();

在這里也沒有爭論。 分配並返回一個新的V_Test

同樣,這里的# of structs 是在函數內部定義的,所有的structs 實例在返回給調用者之前都被分配和編號。

在代碼中,您將看到使用這兩個函數的方法,創建結構,填充它們,顯示內容並釋放分配的內存。

示例輸出

add_vector(): creating 9 structs
#  1: [1, 1.01]
#  2: [2, 2.02]
#  3: [3, 3.03]
#  4: [4, 4.04]
#  5: [5, 5.05]
#  6: [6, 6.06]
#  7: [7, 7.07]
#  8: [8, 8.08]
#  9: [9, 9.09]
9 records were created
9 records were free()'d
add_struct(): creating 4 structs
#  1: [1, 1.01]
#  2: [2, 2.02]
#  3: [3, 3.03]
#  4: [4, 4.04]
4 records were created
4 records were free()'d

C代碼

我只在 MSVC 下編譯過一次。

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int    i;
    double data;

}   Test;

typedef struct
{
    unsigned size;
    Test*    test;

} V_Test;

V_Test*     add_struct();      
Test**      add_vector();

void as_vector_of_pointers();
void as_struct_of_struct();

int main(void)
{
    srand(210728);
    as_vector_of_pointers();
    as_struct_of_struct();
    return 0;
}


Test**      add_vector()
{
    // returns a null terminated array of pointers
    // to test
    int num = rand() % 10;  // 0 to 9 Test
    fprintf(stderr,
        "add_vector(): creating %d structs\n", num);
    // at least one pointer, the terminating one
    Test** ar = (Test**)malloc((1 + num) * sizeof(Test*));
    int    ix = 0;
    for (ix = 0; ix < num; ix += 1)
    {
        ar[ix] = (Test*)malloc(sizeof(Test));
        // sets up ar[i] to a known value
        ar[ix]->i    = 1 + ix;
        ar[ix]->data = 1 + ix + (1 + ix) / 100.;
    };              // for()
    ar[ix] = NULL;  // the terminator one, as in strings
    return ar;
}


V_Test*     add_struct()
{
    // returns a vector of structs inside V_Test,
    // with known 'size', like in 
    // main( int,char**) 
    unsigned num = rand() % 10;  // 0 to 9 Test
    fprintf(stderr, "add_struct(): creating %d structs\n", num);
    V_Test* v  = (V_Test*) malloc(sizeof(V_Test));
    v->size   = num;
    if (num == 0)
    {
        v->test = NULL;
        return v;
    };
    v->test  = (Test*)malloc(num * sizeof(Test));
    for (unsigned ix = 0; ix < num; ix += 1)
    {
        v->test[ix].i = 1 + ix;
        v->test[ix].data = 1 + ix + (1 + ix) / 100.;
    };              // for()
    return v;
}


void as_struct_of_struct()
{
    V_Test* vector = add_struct();
    if (vector->size == 0)
    {
        printf("No records were created!\n");
        free(vector);
        return;
    }
    for ( unsigned count = 0; count < vector->size; count+=1)
    {
        printf("#%3d: [%d, %.2f]\n",
            1 + count,
            vector->test[count].i,
            vector->test[count].data
        );
    };  // for()
    printf("%d records were created\n", vector->size);

    // to free() vector:
    free(vector->test);
    printf("%d records were free()'d\n", vector->size);
    free(vector);
    return;
};


void as_vector_of_pointers()
{
    Test** vector = add_vector();
    // now test the vector to count the number of
    // records generated in the funcion
    if (vector[0] == NULL)
    {
        printf("No records were created!\n");
        free(vector);
        return;
    }
    unsigned count = 0;
    while (vector[count] != NULL)
    {
        printf("#%3d: [%d, %.2f]\n", 1 + count, (vector[count])->i,
               (vector[count])->data);
        count += 1;
    };
    printf("%d records were created\n", count);

    // to free() vector, same way:
    for (unsigned i = 0; i < count; i += 1) free(vector[i]);
    free(vector);
    printf("%d records were free()'d\n", count);
    return;
}

所以警惕:我總是投malloc()指針,因為我提醒自己和其他閱讀代碼的人。 沒有隱式轉換。 沒有必要指出這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM