您好我正在尝试使用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_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;
}
它总是给我“无效使用灵活的阵列成员”。非常感谢,如果有人能够对此有所了解。
答案 0 :(得分:2)
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;
}
答案 1 :(得分:1)
您无法分配到Particle p[]
,只需使用Particle* 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
{
Particle* p;
};
不要忘记在不再需要时释放内存。
答案 2 :(得分:1)
您需要动态分配struct Box
。
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
中有一个指针。如果您希望struct
中的所有数据都是连续的,则灵活的数组成员“技巧”非常有用。如果Point *
中有struct
指针并动态分配,则struct
的内存布局和点将不连续。
您收到错误的原因是您无法在C中分配数组,而box->p
是一个数组(来自n1124 6.7.2.1p16):
但是,当
.
(或->
)运算符的左操作数(指向)具有灵活数组成员且右操作数命名该成员的结构时,其行为如下如果该成员被替换为最长的数组(具有相同的元素类型),该数组不会使结构大于被访问的对象;数组的偏移量应保持为灵活数组成员的偏移量,即使这与替换数组的偏移量不同。如果此数组没有元素,则其行为就好像它有一个元素,但如果尝试访问该元素或生成一个超过它的指针,则行为是未定义的。
除了灵活的阵列成员之外,您还需要在struct
中至少有一个其他成员。
答案 3 :(得分:1)
如果你有一个具有灵活数组成员的结构,那么就不能直接创建该类型的对象,因为编译器不知道你想要多长时间。这就是你尝试用这条线做的事情:
Box b1, b2;
这样的struct
总是需要动态分配,这意味着你只需要声明指向它们的指针。因此,您可以将该声明更改为:
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
似乎是一个不错的选择),因为灵活的数组成员不能是结构的唯一成员。
答案 4 :(得分:0)
答案 5 :(得分:0)
如果您要使用“灵活数组”,它必须是结构中的最后一个元素。这只是因为编译器无法预测下一个元素的偏移量。此外,在分配结构时,您需要为数组元素分配EXTRA内存。
历史记录: 我过去常常看到的一件事就是这样的做法......
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 */
以上将允许人们访问超出[name]的界限。完全合法且有效的C,但有潜在的危险,因为你将故意超越最初声明的[name]界限。
小心那里。