使用C在另一个结构中使用灵活长度的结构数组
您好,我正在尝试使用C实现一个简单的结构:使用C在另一个结构中使用灵活长度的结构数组,c,arrays,struct,C,Arrays,Struct,您好,我正在尝试使用C实现一个简单的结构: 2个盒子,每个盒子包含不同数量的颗粒;在main()中传递的粒子的确切数量 我编写了以下代码: typedef struct Particle{ float x; float y; float vx; float vy; }Particle; typedef struct Box{ Particle p[]; }Box; void make_box(Box *box, int number_of_partic
2个盒子,每个盒子包含不同数量的颗粒;在main()中传递的粒子的确切数量 我编写了以下代码:
typedef struct Particle{
float x;
float y;
float vx;
float vy;
}Particle;
typedef struct Box{
Particle p[];
}Box;
void make_box(Box *box, int number_of_particles);
int main(){
Box b1, b2;
make_box(&b1, 5); //create a box containing 5 particles
make_box(&b2, 10); //create a box containing 10 particles
}
我尝试用以下代码实现make_-box
void make_box(struct Box *box, int no_of_particles){
Particle po[no_of_particles];
po[0].x = 1;
po[1].x = 2;
//so on and so forth...
box->p = po;
}
它总是给我“灵活数组成员的无效使用”。如果有人能对此有所了解,我们将不胜感激。您不能指定给
粒子p[]
,只需使用粒子*p
当然,您需要在堆上分配粒子阵列,而不是在堆栈上!否则,一旦您离开功能make_box
,它将被销毁
void make_box(struct Box *box, int no_of_particles){
Particle* po = (Particle*)malloc(sizeof(Particle)*no_of_particles);
for (int i = 0; i < no_of_particles; i++)
po[0].x = i;
//so on and so forth...
box->p = po;
}
struct Box *box1 = malloc(sizeof *box1 +
sizeof (Particle[number_of_particles]));
for (size_t i=0; i < number_of_particles; ++i)
box1->p[i] = po[i];
/* or memcpy(box1->p, po, sizeof po); */
当不再需要内存时,不要忘记释放内存。在Box struct中,为什么不使用指向粒子的指针来创建动态数组
void make_box(struct Box *box, int no_of_particles){
Particle po[no_of_particles];
//...
box->p = po;
}
po
是一个局部变量,它的存储在堆栈上自动分配;返回它的地址是个坏主意。相反,您应该从堆中分配内存,并记住在处理完这些框后释放内存:
#include <stdlib.h>
#include <stdio.h>
typedef struct Particle_ {
float x;
float y;
float vx;
float vy;
} Particle;
typedef struct Box_ {
Particle *p;
} Box;
void make_box(Box *box, int no_of_particles);
void make_box(Box *box, int no_of_particles){
Particle *po = (Particle *) malloc ( no_of_particles*sizeof(Particle) );
po[0].x = 1;
po[1].y = 2;
//so on and so forth...
box->p = po;
}
void destroy_box(Box *box){
free(box->p);
}
int main(){
Box b1, b2;
make_box(&b1, 5); //create a box containing 5 particles
make_box(&b2, 10); //create a box containing 10 particles
// do the job...
printf("box b1, point 0, x: %5.2f\n", b1.p[0].x);
printf("box b2, point 1, y: %5.2f\n", b2.p[1].y);
destroy_box(&b1);
destroy_box(&b2);
return 0;
}
#包括
#包括
类型定义结构粒子{
浮动x;
浮动y;
浮动vx;
浮球;
}粒子;
类型定义结构框{
粒子*p;
}盒子;
void make_box(box*box,int no_的粒子);
void make_box(box*box,int no_的粒子){
Particle*po=(Particle*)malloc(无粒子数*sizeof(粒子));
po[0].x=1;
po[1],y=2;
//诸如此类。。。
方框->p=po;
}
空盒(盒*盒){
自由(方框->p);
}
int main(){
框b1、b2;
make_box(&b1,5);//创建一个包含5个粒子的框
make_-box(&b2,10);//创建一个包含10个粒子的框
//做这项工作。。。
printf(“b1框,点0,x:%5.2f\n”,b1.p[0].x);
printf(“框b2,点1,y:%5.2f\n”,b2.p[1].y);
销毁包装盒(b1和b1);
摧毁_盒(&b2);
返回0;
}
您需要动态分配struct-Box
void make_box(struct Box *box, int no_of_particles){
Particle* po = (Particle*)malloc(sizeof(Particle)*no_of_particles);
for (int i = 0; i < no_of_particles; i++)
po[0].x = i;
//so on and so forth...
box->p = po;
}
struct Box *box1 = malloc(sizeof *box1 +
sizeof (Particle[number_of_particles]));
for (size_t i=0; i < number_of_particles; ++i)
box1->p[i] = po[i];
/* or memcpy(box1->p, po, sizeof po); */
struct Box*box1=malloc(sizeof*box1+
sizeof(粒子[粒子数]);
对于(尺寸i=0;i<粒子数;++i)
框1->p[i]=po[i];
/*或memcpy(框1->p,po,po尺寸)*/
但是,如果您正在执行上述操作,您还可以声明struct-Box
中包含指针。如果希望struct
中的所有数据都是连续的,那么灵活的数组成员“技巧”非常有用。如果在struct
中有一个点*
指针并动态分配它,那么struct
和点的内存布局将不连续
出现错误的原因是无法在C中指定数组,而box->p
是数组(来自N11246.7.2.1p16):
但是,当
(或->
)运算符的左操作数是(指向)具有灵活数组成员的结构,而右操作数命名该成员时,其行为就好像该成员被替换为最长的数组(具有相同的元素类型)这不会使结构大于正在访问的对象;阵列的偏移量应保持柔性阵列构件的偏移量,即使这与替换阵列的偏移量不同。如果这个数组没有元素,它的行为就好像它有一个元素一样,但如果试图访问该元素或生成一个超过该元素的指针,则该行为是未定义的
除灵活数组成员外,您的
结构中还需要至少有一个其他成员。如果您的结构具有灵活数组成员,则无法直接创建该类型的对象,因为编译器不知道您希望它的长度。这就是你试图用这一行来做的:
Box b1, b2;
这样的struct
s总是需要动态分配,这意味着您只能声明指向它们的指针。因此,您将该声明更改为:
Box *b1, *b2;
…并更改make_box()
函数以返回这样的指针:
Box *make_box(int no_of_particles)
{
Box *box = malloc(sizeof *box + no_of_particles * sizeof box->p[0]);
if (box)
{
box->p[0].x = 1;
box->p[1].x = 2;
//so on and so forth...
}
return box;
}
void destroy_box(Box *box){
free(box);
}
int main()
{
Box *b1 = make_box(5); //create a box containing 5 particles
Box *b2 = make_box(10); //create a box containing 10 particles
// Test that b1 and b2 are not NULL, then do the job...
destroy_box(b1);
destroy_box(b2);
return 0;
}
PS:
您还需要将至少一个其他成员添加到Box结构中(no_of_particles
似乎是一个不错的选择),因为灵活数组成员不能是结构的唯一成员。如果要使用“灵活数组”,它必须是结构中的最后一个元素。这只是因为编译器无法预测下一个元素的偏移量。此外,在分配结构时,需要为数组元素分配额外的内存
历史注释:
过去我经常看到的一件事是这样的练习
struct a {
int x, y, z;
char name[1];
};
struct a * ptr;
ptr = (struct a*) malloc (sizeof (a) + EXTRA SPACE FOR name);
or
ptr = (struct a*) buffer; /* <buffer> would have been a passed character array */
结构a{
int x,y,z;
字符名[1];
};
结构a*ptr;
ptr=(结构a*)malloc(sizeof(a)+名称的额外空格);
或
ptr=(结构a*)缓冲区;/*将是传递的字符数组*/
上述内容将允许用户访问超出[name]范围的内容。完全合法且有效的C,但有潜在危险,因为您将故意超出最初声明的[name]界限
小心点。如果我没记错的话,C不允许使用数组大小的变量。C99允许。它被称为可变长度数组,或VLA。C99还通过引入“灵活的数组成员”来祝福“结构黑客”。谢谢,我一直是Java爱好者,对C来说是新手。内存分配的想法让我发疯。在main()中,我可以知道如何访问粒子阵列的每个元素吗?像Prtf(“%f”),b1.p(1)x)@费德里克,您可能想尝试BeeHEM GC,用于C或C++。您最近的观察是一个好的观点,但是MaxixBox()的第一条指令对我来说毫无意义。更好:Box=malloc(Box的大小);如果(长方体){box->nParticle=no_of_粒子;长方体->p=malloc(no_of_particlessizeof(粒子));如果(长方体->p{etc..,则无效销毁长方体(长方体*长方体){if(长方体){if(长方体){if