我对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
struct
数组?
非常感谢。
答案 0 :(得分:1)
这是一个简短的代码,展示了如何实现它:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.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;
} Base_t;
int main() {
Detail_t data;
data.power = data.t1 = data.dT = 1;
Detail_t data2;
data2.power = data2.t1 = data2.dT = 2;
Base_t bases[10];//array of Base_t
int size = 1;//initial size of Detail_t array
bases[0].data = NULL;
bases[0].data = (Detail_t* )realloc(bases[0].data, size * sizeof(Detail_t));//first realloc acts as a malloc because bases[0].data is NULL at first
if (bases[0].data != NULL) {//if malloc(realloc) was successful
bases[0].data[0] = data;//store data
}
size = 2;//increase size of Detail_t array by 1
bases[0].data = (Detail_t* )realloc(bases[0].data, size * sizeof(Detail_t));//realloc new size
if (bases[0].data != NULL) {//if it didn't fail
bases[0].data[1] = data2;//store new data
}
printf("%d\n", bases[0].data[0].power);//print first data power
printf("%d", bases[0].data[1].power);//print second data power
free(bases[0].data);//free memory
}
这有帮助吗?我想混淆初学者的部分就是演员。 malloc和realloc将一个类型为void *的指针返回给已分配的内存,然后您可以将其转换为您正在使用的类型。
答案 1 :(得分:1)
这是另一种方式......
#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
答案 2 :(得分:0)
示例:
typedef struct Base {
uuid_array unique_id;
int n_dataIems;
Detail_t *data;
} Base_t;
void example(void)
{
Base_t t;
int i;
t.n_dataItems= 0;
t.data= 0;
for (i=0; i<4; i++)
{
t.data= realloc(t.data, ++t.n_dataItems * sizeof(Detail_t));
t.data[i].power= i;
}
}
(错误检查已省略。)
注意:细节的定义必须在Base之前。