C 使用双指针迭代结构数组并使用双指针访问元素
我有一辆嵌套结构车C 使用双指针迭代结构数组并使用双指针访问元素,c,pointers,struct,C,Pointers,Struct,我有一辆嵌套结构车 struct employee{ int id; unsigned int department_id; char initials; }; struct car{ int number; unsigned int tagged; struct employee emp; }; struct car carObj[5] = { {1, 1, {11, 111,'c'}}, {2, 0, {22, 222, '
struct employee{
int id;
unsigned int department_id;
char initials;
};
struct car{
int number;
unsigned int tagged;
struct employee emp;
};
struct car carObj[5] = {
{1, 1, {11, 111,'c'}},
{2, 0, {22, 222, 'd'}},
{3, 1, {33, 333, 'e'}},
{4, 1, {44, 444, 'f'}},
{5, 0, {55, 555, 'g'}}
};
struct car *carPtr;
然后我有一个结构车的对象
struct employee{
int id;
unsigned int department_id;
char initials;
};
struct car{
int number;
unsigned int tagged;
struct employee emp;
};
struct car carObj[5] = {
{1, 1, {11, 111,'c'}},
{2, 0, {22, 222, 'd'}},
{3, 1, {33, 333, 'e'}},
{4, 1, {44, 444, 'f'}},
{5, 0, {55, 555, 'g'}}
};
struct car *carPtr;
接下来,我有一个指向struct car的指针
struct employee{
int id;
unsigned int department_id;
char initials;
};
struct car{
int number;
unsigned int tagged;
struct employee emp;
};
struct car carObj[5] = {
{1, 1, {11, 111,'c'}},
{2, 0, {22, 222, 'd'}},
{3, 1, {33, 333, 'e'}},
{4, 1, {44, 444, 'f'}},
{5, 0, {55, 555, 'g'}}
};
struct car *carPtr;
我必须用对象carObj中的各种元素填充这个“carPtr”指针。
我将为汽车的每个对象分配一个新内存,并复制其中的数组元素
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct employee{
int id;
unsigned int department_id;
char initials;
};
struct car{
int number;
unsigned int tagged;
struct employee emp;
};
struct car carObj[5] = {
{1, 1, {11, 111,'c'}},
{2, 0, {22, 222, 'd'}},
{3, 1, {33, 333, 'e'}},
{4, 1, {44, 444, 'f'}},
{5, 0, {55, 555, 'g'}}
};
struct car *carPtr;
void fillData(struct car **t)
{
int cnt = 0;
for(int i = 0; i < 5; i++)
{
cnt++;
if(*t == NULL)
{
*t = calloc(cnt, sizeof(struct car));
}
else
{
*t = realloc(*t, (cnt*sizeof(struct car)));
}
memcpy(& ______, &carObj[i], sizeof(struct car));
printf("%s(): number = %d, tagged = %d, id = %d, department = %d, initials = %c\n", __func__, ____.number, _____.tagged, ____.emp.id, ____.emp.department_id, ______.emp.initials);
}
}
int main()
{
sendData(&carPtr);
for(int i = 0; i < 5; i++)
{
printf("%s(): number = %d, tagged = %d, id = %d, department = %d, initials = %c\n", __func__, carPtr[i].number, carPtr[i].tagged, carPtr[i].emp.id, carPtr[i].emp.department_id, carPtr[i].emp.initials);
}
return 0;
}
#包括
#包括
#包括
结构雇员{
int-id;
未签名的int部门id;
字符首字母;
};
结构车{
整数;
无符号整数标记;
结构员工emp;
};
结构车carObj[5]={
{1,1,{11,111,'c'},
{2,0,{22,222,'d'},
{3,1,{33,333,'e'},
{4,1,{44444,'f'},
{5,0,{55555,'g'}
};
结构车*carPtr;
无效填充数据(结构车**t)
{
int-cnt=0;
对于(int i=0;i<5;i++)
{
cnt++;
如果(*t==NULL)
{
*t=calloc(cnt,sizeof(struct-car));
}
其他的
{
*t=realloc(*t,(cnt*sizeof(结构车));
}
memcpy(&uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,&carObj[i],sizeof(struct car));
printf(“%s():编号=%d,标记=%d,id=%d,部门=%d,缩写=%c\n“,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
}
}
int main()
{
sendData&carPtr;
对于(int i=0;i<5;i++)
{
printf(“%s():编号=%d,标记=%d,id=%d,部门=%d,缩写=%c\n“,\uu func\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
}
返回0;
}
问题:如何使用双指针访问单个元素?
在上面的memcpy中,我标记了一个空白“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”。我需要在那里写什么语句来访问最近分配的指针?
在printf中,我应该写什么语句来访问指针的元素。您很接近了,但是需要做一些改进:
fillData()
选择一个有意义的返回类型,它将在调用者中指示成功/失败fillData()
之前,您知道元素的数量,因此只需分配一次并复制,然后carObj[]
,这将是:
int main (void)
{
struct car carObj[ ] = {{1, 1, {11, 111,'c'}}, /* avoid global variables */
{2, 0, {22, 222, 'd'}},
{3, 1, {33, 333, 'e'}},
{4, 1, {44, 444, 'f'}},
{5, 0, {55, 555, 'g'}}},
*carPtr = NULL; /* must initialize pointer NULL */
size_t nelem = sizeof carObj/sizeof *carObj; /* number of elements */
...
if (!fillData (&carPtr, carObj, nelem)) /* validate function return */
return 1;
由于在fillData()
中进行分配,因此必须有一种方法向调用函数指示分配是成功还是失败,以便在使用分配的内存块之前在调用方中进行验证,例如
/* choose meaningful return type that indicates success/failure */
struct car *fillData (struct car **t, struct car *obj, size_t nelem)
{
*t = calloc (nelem, sizeof **t); /* number of elements known, just allocate */
if (t == NULL) { /* valdiate every allocation */
perror ("calloc-t");
return NULL;
}
return memcpy (*t, obj, nelem * sizeof **t); /* return pointer to allocated block */
}
(注意:通过使用取消引用的指针设置分配的类型大小,您永远不会出错)
如上所示,您知道元素的数量nelem
,因此无需循环fillData()
,只需分配、验证和复制即可
通过将必要的参数传递给fillData()
,可以避免使用任何全局变量,并且通过选择有意义的返回,可以验证块是否已在main()
中分配和填充。您在main()
中的调用将是:
int main (void)
{
struct car carObj[ ] = {{1, 1, {11, 111,'c'}}, /* avoid global variables */
{2, 0, {22, 222, 'd'}},
{3, 1, {33, 333, 'e'}},
{4, 1, {44, 444, 'f'}},
{5, 0, {55, 555, 'g'}}},
*carPtr = NULL; /* must initialize pointer NULL */
size_t nelem = sizeof carObj/sizeof *carObj; /* number of elements */
...
if (!fillData (&carPtr, carObj, nelem)) /* validate function return */
return 1;
总而言之,你应该:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct employee {
int id;
unsigned int department_id;
char initials;
};
struct car {
int number;
unsigned int tagged;
struct employee emp;
};
/* choose meaningful return type that indicates success/failure */
struct car *fillData (struct car **t, struct car *obj, size_t nelem)
{
*t = calloc (nelem, sizeof **t); /* number of elements known, just allocate */
if (t == NULL) { /* valdiate every allocation */
perror ("calloc-t");
return NULL;
}
return memcpy (*t, obj, nelem * sizeof **t); /* return pointer to allocated block */
}
int main (void)
{
struct car carObj[ ] = {{1, 1, {11, 111,'c'}}, /* avoid global variables */
{2, 0, {22, 222, 'd'}},
{3, 1, {33, 333, 'e'}},
{4, 1, {44, 444, 'f'}},
{5, 0, {55, 555, 'g'}}},
*carPtr = NULL; /* must initialize pointer NULL */
size_t nelem = sizeof carObj/sizeof *carObj; /* number of elements */
if (!fillData (&carPtr, carObj, nelem)) /* validate function return */
return 1;
// sendData (&carPtr);
for (size_t i = 0; i < nelem; i++) /* output results */
{
printf ("%s(): number = %d, tagged = %u, id = %d, department = %d, initials = %c\n",
__func__, carPtr[i].number, carPtr[i].tagged, carPtr[i].emp.id,
carPtr[i].emp.department_id, carPtr[i].emp.initials);
}
free (carPtr); /* free allocated memory */
}
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于所分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要它时可以释放它
必须使用内存错误检查程序,以确保您不会试图访问内存或写入超出/超出分配的块的边界,尝试在未初始化的值上读取或基于条件跳转,最后确认释放所有已分配的内存
对于Linux,valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很容易使用,只需运行程序即可
$ valgrind ./bin/car_employee
==14725== Memcheck, a memory error detector
==14725== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14725== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14725== Command: ./bin/car_employee
==14725==
main(): number = 1, tagged = 1, id = 11, department = 111, initials = c
main(): number = 2, tagged = 0, id = 22, department = 222, initials = d
main(): number = 3, tagged = 1, id = 33, department = 333, initials = e
main(): number = 4, tagged = 1, id = 44, department = 444, initials = f
main(): number = 5, tagged = 0, id = 55, department = 555, initials = g
==14725==
==14725== HEAP SUMMARY:
==14725== in use at exit: 0 bytes in 0 blocks
==14725== total heap usage: 2 allocs, 2 frees, 1,124 bytes allocated
==14725==
==14725== All heap blocks were freed -- no leaks are possible
==14725==
==14725== For counts of detected and suppressed errors, rerun with: -v
==14725== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认已释放所有已分配的内存,并且没有内存错误
仔细检查一下,如果您还有其他问题,请告诉我。
memcpy(*t,&carObj[i],sizeof(struct-car))
和(*t)->number
,等等。更简单的是,结构是可赋值的左值,:**t=carObj[i]
(但重新分配并始终分配给第一个元素是没有意义的)(*t)[i]=carObj[i]代码>。此外,如果您知道项目的数量,为什么不一次性为所有项目分配足够的空间,而不是在循环中重复重新分配?谢谢各位的建议。Jonathan我认为在memcpy中,如果我们使用*t,那么在重新分配内存后,它将始终覆盖第一个元素地址。这是一个示例代码,而在实际代码中,我必须分配内存并在代码中填充数据。Dmitri我不知道实时环境中的项目数量,而且我也不会拥有carObj结构,在这种情况下,我将不得不自己填充数据。我想你需要struct employee*emp[]代码>因为员工可以使用多辆车,一辆车可以被多个员工使用。需要动态分配和取消分配非常感谢David为您所做的一切努力。仅供参考,在实际项目环境中,我不会提前知道元素的确切数量。在实时环境中,我将接收一个struct car对象,该对象将存储在动态分配的指针中。因此,我每次都必须为每个汽车对象分配内存,并将接收到的汽车信息存储在其中。假设上面的代码正在服务器上运行,它将在服务器上保存汽车详细信息。客户端每次都会向服务器发送一个汽车信息,服务器会保存它。好的,在这种情况下,你必须有办法找到最后一个元素(比如sentinel NULL或bla)