struct 内指向动态结构数组的指针 C

星鹰 34

我对 C 中的常见问题之一感到困惑,即内存管理和指针。我有三个结构,像这样。

typedef struct {
   uint8_t  uuid[16];
} uuid_array;

typedef struct Detail {
   int8_t power;
   uint32_t t1;
   uint32_t dT;
} Detail_t;

typedef struct Base {
   uuid_array unique_id;
   Detail_t *data;
} Base_t;

我想创建十个Base_t结构,我希望data每个结构中的指针Base_t struct指向一个动态增长的Detail_t结构数组

我知道我应该使用malloc()realloc()但我没有使用这些功能的经验,我对它们的工作方式感到非常困惑。

data指针如何指向动态大小的Detail_t structs数组

非常感谢你。

马洪里·莫里安库默

这是另一种方式...

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

typedef struct
   {
   uint8_t  uuid[16];
   } uuid_array;

typedef struct Detail
   {
   int8_t   power;
   uint32_t t1;
   uint32_t dT;
   } Detail_t;

typedef struct Base
   {
   uuid_array  unique_id;
   Detail_t   *data;
   uint32_t    dataItemCnt;  /* In struct Base you will want to add an item int **
                           ** n_dataItems to keep track of how many items     **
                           ** there are in your array. – Paul Ogilvie         */
   } Base_t;

#define SUCCESS 0

/**********************************************************
** Append a Detail_t structure to the data field of the to Base_t structure..
*/
int AppendData(Base_t *baseT, int8_t power, uint32_t t1, uint32_t dT)
   {
   int rCode = SUCCESS;
   Detail_t *data=NULL;

   /* Verify that the caller did not pass NULL as the Base_t structure address. */
   if(!baseT)
      {
      rCode=EINVAL;     /* Invalid Base_t value argument. */
      goto CLEANUP;
      }

  /* Increase the size of the baseT->data array sufficient for an additional Detail_t structure. */
   errno=SUCCESS;
   data=realloc(baseT->data, (baseT->dataItemCnt + 1) * sizeof(Detail_t));
   if(!data)  /* Verify that the realloc() succeeded. */
      {
      rCode=errno;
      goto CLEANUP;
      }

   /* Cause the Base_t data array to point to the newly (re-alloced) memory. */
   baseT->data = data; 

   /* Initialize the new Detail_t structure values. */
   baseT->data[baseT->dataItemCnt].power = power;
   baseT->data[baseT->dataItemCnt].t1    = t1;
   baseT->data[baseT->dataItemCnt].dT    = dT;

   /* Increment Base_t->dataItemCnt to reflect the appended Detail_t structure. */
   ++baseT->dataItemCnt;

CLEANUP:

   return(rCode);
   }

/**********************************************************
** Free a previously allocated Base_t type.
*/
int FreeBaseT(Base_t **baseT)
   {
   int rCode = SUCCESS;

   /* Verify that the caller did not pass in NULL for baseT */
   if(!baseT)
      {
      rCode=EINVAL;     /* Invalid Base_t value argument. */
      goto CLEANUP;
      }

   /* verify that the the Base_t structure is not already free. */
   if(!*baseT)
      {
      rCode=EALREADY;   /* The Base_t structure is NULL  (Already free). */
      goto CLEANUP;
      }

   /* If there are Detail_t structures in the data array, free the data array. */
   if((*baseT)->data)
      free((*baseT)->data);

   /* Free the memory previously allocated to the Base_t structure. */
   free(*baseT);
   *baseT = NULL;   /* Eliminate the caller's reference to the freed memory. */

CLEANUP:

   return(rCode);
   }

/**********************************************************
** Allocate a Base_t type.
*/
int AllocBaseT(Base_t **baseT_OUT, uint8_t uuid[16])
   {
   int     rCode = SUCCESS;
   Base_t *baseT = NULL;

   /* Allocate memory to the Base_t structure. */
   errno=SUCCESS;
   baseT = malloc(sizeof(Base_t));
   if(!baseT)
      {
      rCode=errno;
      goto CLEANUP;
      }

   /* Initialize the initial values of the Base_t structure. */
   memset(baseT, 0, sizeof(Base_t));
   memcpy(&baseT->unique_id.uuid, uuid, 16);

   /* Ensure that the caller passed a non-NULL address,
      if so, return the address of the allocated Base_t structure. */
   if(baseT_OUT)
      {
      *baseT_OUT = baseT;
      baseT = NULL;
      }

CLEANUP:

   /* If the caller passed-in a NULL for baseT_OUT,
      free the allocated memory to that the program does not cause a leak. */
   if(baseT)
      {
      int rc=FreeBaseT(&baseT);
      if(rc && !rCode)
         rCode=rc;
      }

   return(rCode);
   }

/**********************************************************
** Dump a base_t structure.
*/
int DumpBaseT(Base_t *baseT)
   {
   int      rCode   = SUCCESS;
   uint32_t index;

   if(!baseT)
      {
      rCode=EINVAL;     /* Invalid Base_t value argument. */
      goto CLEANUP;
      }

   /* Print the Base_t->unique_array->uuid */
   printf("UUID: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
      baseT->unique_id.uuid[0],
      baseT->unique_id.uuid[1],
      baseT->unique_id.uuid[2],
      baseT->unique_id.uuid[3],
      baseT->unique_id.uuid[4],
      baseT->unique_id.uuid[5],
      baseT->unique_id.uuid[6],
      baseT->unique_id.uuid[7],
      baseT->unique_id.uuid[8],
      baseT->unique_id.uuid[9],
      baseT->unique_id.uuid[10],
      baseT->unique_id.uuid[11],
      baseT->unique_id.uuid[12],
      baseT->unique_id.uuid[13],
      baseT->unique_id.uuid[14],
      baseT->unique_id.uuid[15]
      );

   /* Print the Base_t->Detail_t values */   
   printf("Number of data items: %u\n",  baseT->dataItemCnt);
   for(index=0; index < baseT->dataItemCnt; ++index)
      {
      printf("   data[%d] power=%d t1=%d dT=%d\n",
         index,
         baseT->data[index].power,
         baseT->data[index].t1,
         baseT->data[index].dT
         );
      }

CLEANUP:

   return(rCode);
   }

/**********************************************************
** Program start.
*/
int main(int argC, char *argV[])
   {
   int     rCode   = SUCCESS;
   Base_t *baset_A = NULL;
   uint8_t  uuid[16] =
      {
      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
      0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
      };

   /* Allocate memory for a Base_t structure (with no attached data) */
   rCode=AllocBaseT(&baset_A, uuid);
   if(rCode)
      {
      fprintf(stderr, "AllocBaseT() reports: %d %s\n", rCode, strerror(rCode));
      goto CLEANUP;
      }

   /* Allocate some data (Detail_t) to the Base_t structure. */
   rCode=AppendData(baset_A, 1, 1000, 1111);
   if(rCode)
      {
      fprintf(stderr, "AppendData() reports: %d %s\n", rCode, strerror(rCode));
      goto CLEANUP;
      }

   rCode=AppendData(baset_A, 2, 2000, 2222);
   if(rCode)
      {
      fprintf(stderr, "AppendData() reports: %d %s\n", rCode, strerror(rCode));
      goto CLEANUP;
      }

   rCode=AppendData(baset_A, 3, 3000, 3333);
   if(rCode)
      {
      fprintf(stderr, "AppendData() reports: %d %s\n", rCode, strerror(rCode));
      goto CLEANUP;
      }

   /* Print out the Base_t structure. */
   rCode=DumpBaseT(baset_A);
   if(rCode)
      {
      fprintf(stderr, "DumpBaseT() reports: %d %s\n", rCode, strerror(rCode));
      goto CLEANUP;
      }

CLEANUP:

   /* Free the memory allocated to the Base_t structure. */ 
   if(baset_A)
      {
      int rc=FreeBaseT(&baset_A);
      if(rc)
         fprintf(stderr, "FreeBaseT() reports: %d %s\n", rCode, strerror(rCode));
      }

   return(rCode);
   }

输出:

UUID: 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
Number of data items: 3
   data[0] power=1 t1=1000 dT=1111
   data[1] power=2 t1=2000 dT=2222
   data[2] power=3 t1=3000 dT=3333

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章