簡體   English   中英

使用C的另一個struct內部的靈活長度struct數組

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM