[英]flexible length struct array inside another struct using C
您好我正在嘗試使用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;
}
它總是給我“無效使用靈活的陣列成員”。 非常感謝,如果有人能夠對此有所了解。
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;
}
你不能分配給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;
};
並且不要忘記在不再需要時釋放內存。
您需要動態分配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
是連續的。 如果你在struct
有一個Point *
指針並動態分配它,那么struct
和points的內存布局將不會是連續的。
您收到錯誤的原因是您無法在C中分配數組,而box- box->p
是一個數組(來自n1124 6.7.2.1p16):
但是,當一個
.
(或->
)運算符有一個左操作數,它是一個帶有靈活數組成員的結構(一個指針),右操作數命名該成員,它的行為就好像該成員被最長的數組替換(具有相同的元素類型) )不會使結構大於被訪問的對象; 數組的偏移量應保持為靈活數組成員的偏移量,即使這與替換數組的偏移量不同。 如果此數組沒有元素,則其行為就好像它有一個元素,但如果嘗試訪問該元素或生成一個超過它的指針,則行為未定義。
除了靈活的數組成員之外,您還需要在struct
中至少包含一個其他成員。
如果你有一個具有靈活數組成員的結構,那么就不能直接創建該類型的對象,因為編譯器不知道你想要多長時間。 這就是你嘗試用這條線做的事情:
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
似乎是一個不錯的選擇),因為靈活的數組成員不能是結構的唯一成員。
在Box結構中,為什么不使用指向粒子的指針,以便創建動態數組呢?
如果你想要一個“靈活的數組”,它必須是結構中的最后一個元素。 這只是因為編譯器無法預測下一個元素的偏移量。 此外,在分配結構時,您需要為數組元素分配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]界限。
小心那里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.