如何使用指向结构的多个指针,该结构包含指向具有多个指针的另一个结构的指针?

时间:2021-03-11 04:55:54

标签: c pointers struct

我正在尝试使用指向一个结构的指针数组,该结构中包含一个指向另一个与指针数组一起使用的结构的指针。

我可以为两个单一结构编写代码并且它可以工作。但是,我不确定如何处理指针数组的引入。 示例代码:

typedef struct {
    double vx;
} particle_t;
    
typedef struct {
    int m;
    int n;
    particle_t *inparticles;    // Pointer to particles inside grid
} grid_t;
    
particle_t *particles = (particle_t*) malloc( 3 * sizeof(particle_t) );
grid_t *grid = (grid_t*) malloc( 3 * sizeof(grid_t) ); // trying 3 pointers

if( particles==NULL || grid==NULL ){
    puts("Unable to allocate memory");
    exit(1);}

// fill the structure 
grid[1].inparticles = particles[1]; // I am not sure how to link these
grid[2].inparticles = particles[2]; // these lines give incompatible types error
grid[3].inparticles = particles[3];
grid[1].m = 5;
grid[1].n = 3;
grid[1].inparticles -> vx = 15;

先谢谢你!

更新:

我意识到我应该做的是使用粒子内指针指向同一个网格指针中的多个粒子?我如何更改代码以便我能够做到这一点? 例如:

grid[0].inparticles[0] = particles[0];
grid[0].inparticles[1] = particles[1];
grid[0].inparticles[2] = particles[2];

以某种方式将其声明为数组?我还需要为它分配内存吗?

5 个答案:

答案 0 :(得分:1)

particles 的每个成员都有类型 particle_tinparticlesgrid_t 成员的类型为 particle_t *。所以你想要:

grid[1].inparticles = &particles[1];
grid[2].inparticles = &particles[2];
grid[3].inparticles = &particles[3];

解决您的更新问题,如果您想让 inparticles 指向 particles 的各个成员,则需要将 inparticles 更改为指向指针的指针:

typedef struct {
    int m;
    int n;
    particle_t **inparticles;
} grid_t;

然后你必须为一个指针数组分配空间,然后分配每个指针:

grid[0].inparticles = malloc(3 * sizeof(particle_t *));
grid[0].inparticles[0] = &particles[0];
grid[0].inparticles[1] = &particles[1];
grid[0].inparticles[2] = &particles[2];

答案 1 :(得分:1)

问题

设计

<块引用>

我正在尝试使用指向一个结构的指针数组,该结构中包含一个指向另一个与指针数组一起使用的结构的指针。

换句话说,我们必须找到一种方法来设计“一个指针数组结构,其中包含一个指针到另一个struct 用作数组”。

我会专注于此。

指针数组

<块引用>

但是,我不知道如何处理指针数组的引入。

好吧,我们在您的代码中没有任何指针数组……您必须先创建一个。

C 指针、数组、结构和它们的所有组合在互联网上无数 个线程,已经多次回答。我将向您展示一些基本示例,以便您可以启动并运行,只是不要指望我给您提供完整的指导课程。


解决方案

设计

这是代码(我更改了一些变量名称以使其更具可读性):

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    double value;
}Particle;

typedef struct
{
    int width;
    int height;
    Particle *particles;
}Grid;

Grid *createGrid(int width, int height)
{
    Grid *result = malloc(sizeof(Grid));
    if (result == NULL)
    {
        printf("Error while allocating memory for the grid structure!\n");
        exit(1);
    }else
    {
        result->width = width;
        result->height = height;
        result->particles = malloc(sizeof(Particle) * width*height);
    }
    return result;
}

void destroyGrid(Grid *grid)
{
    free(grid->particles);
    free(grid);
}

int main()
{
    Grid *grids[3];
    for (int i = 0; i < 3; i++)
        grids[i] = createGrid(5, 3);
    
    /* Assign, modify, read or copy values from the array of pointers here */
    
    for (int i = 0; i < 3; i++)
        destroyGrid(grids[i]);
    return 0;
}

如您所见,我引入了 2 个函数来让您的生活更轻松:createGriddestroyGrid

第一个需要您指定 2 个参数:网格的 widthheight(代码中的 mn)。然后该函数将分配内存并返回一个指针到它刚刚创建的网格。

第二个需要您指定 1 个参数:一个 指针 到一个网格。然后该函数将释放第一个函数分配的所有内存,避免任何内存泄漏。

我还在主函数中添加了一个指针数组grids。这样,结合上述函数的使用(都在主函数中),解决了第一个问题。

最终设计如下:
“我们有一个指针数组,指向一个结构grids),其中包含一个指针,指向另一个结构< /strong> (particles) 应该用作数组”。

指针数组

您现在可能想知道:“好吧,那么我应该如何使用这个指向结构的指针数组呢?”正如我之前所说,我只会向您展示一个实际示例。

假设您要将第一个网格的第三个粒子的值设置为 2.7182:(您应该在我注释为 /* Assign, modify, read or copy values from the array of pointers here */ 的地方插入此代码)

grids[0]->particles[2].value = 2.7182;

这可以从左到右读作:“从指针数组 grids 中,获取索引为 0 的元素(指向 Grid 结构的第一个指针)。访问它的结构成员 particles,它是一个指针。将该指针视为一个数组并获取索引为 2 的元素(第三个 Particle 结构)。访问其成员 value 并将其分配给它值 2.7182"

然后你可以做一些事情,比如将一个粒子复制到另一个:

grids[1]->particles[1] = grids[0]->particles[2];

这里有一些链接可以更好地理解指针、数组和结构。实践和实验是处理它们的最佳方式:


更新

<块引用>

我意识到我应该做的是使用粒子内指针指向同一个网格指针中的多个粒子

<块引用>

我需要使用一个单独的指向粒子的指针数组。网格结构内部的数组只是指向一个粒子的子集。

目标:“使用粒子内指针指向多个(序列或非序列?)粒子(在其他地方管理)的子集”。

如果你想要顺序解决方案,你可以使用一个指针,表示一个指向数组的基地址(或偏移,如果你只想要一个子集)的指针(这是一个指向数组的指针)。这样做的优点是不需要为每个指针分配额外的内存(因为只需要基地址),但缺点是只能访问彼此相邻的粒子。

示例:

typedef struct
{
    int width;
    int height;
    Particle *subparticles; //Represents a pointer to an array subset
}Grid;
    /*...*/

    grids[0]->subparticles = &particles[0];
    grids[1]->subparticles = &particles[1];

    printf("%f equals %f", grids[0]->subparticles[1].value, grids[1]->subparticles[0].value);

    /*...*/

但是,如果您想要非顺序解决方案,则可以使用双指针(表示指针数组),同时必须手动为该数组分配内存。这为您提供了更大的灵活性,但以内存分配开销为代价。

typedef struct
{
    /*...other members...*/
    Particle **subparticles;
}Grid;

Grid *createGrid(int subparticlesCount)
{
    Grid *result = malloc(sizeof(Grid));
    if (result == NULL)
    {
        printf("Error while allocating memory for the grid structure!\n");
        exit(1);
    }else
    {
        result->subparticles = malloc(sizeof(Particle *) * subparticlesCount);
    }
    return result;
}
    /*...*/

    grids[0]->subparticles[0] = &particles[1];
    grids[0]->subparticles[1] = &particles[5];
    grids[0]->subparticles[2] = &particles[3];
    grids[1]->subparticles[0] = &particles[3];

    printf("%f equals %f", grids[0]->subparticles[2]->value, grids[1]->subparticles[0]->value);

    /*...*/

答案 2 :(得分:1)

如果该字段是其 public static void main(String[] args) { SwingUtilities.invokeLater(() -> buildGui()); } private static void buildGui() { JFrame frame = new JFrame(); JTextArea textArea = new JTextArea(5, 20); // set default font size to 10 to match JSlider starting position textArea.setFont(new Font(textArea.getFont().getName(), textArea.getFont().getStyle(), 10)); frame.add(textArea, BorderLayout.CENTER); // set up slider JSlider slider = new JSlider(JSlider.HORIZONTAL, 10, 30, 10); slider.setMajorTickSpacing(5); slider.setMinorTickSpacing(1); slider.setPaintTicks(true); slider.setPaintLabels(true); frame.add(slider, BorderLayout.SOUTH); // create and add change listener slider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { int fontSize = slider.getValue(); Font currentFont = textArea.getFont(); // get the current font and set the modified font size textArea.setFont(new Font(currentFont.getName(), currentFont.getStyle(), fontSize)); } }); frame.pack(); frame.setVisible(true); } last,而不是作为指针(指向某个数组)的字段,则可以将其设为 flexible array member。所以声明

struct

有关示例和详细信息,以及 C 标准(如 this answer §6.7.2.1)或 n1570,请参见 this C reference

某些情况下,避免指针和间接引用可能会略微加快您的代码速度(因为 CPU cache)。灵活数组成员还避免了为该内部灵活数组添加额外的 typedef struct { int m; int n; unsigned count; particle_t inparticle_arr[]; // flexible array of count elements } grid_t;

为了调试和避免 buffer overflows,编译您的 C 代码时使用 GCC 作为 free 调用,并且还使用 valgrind(或 address sanitizer)。

答案 3 :(得分:1)

根据问题和随后的评论,我的理解是您要创建一个网格,该网格应包含一个指向指针数组(即多个指针)的指针,其中每个指针指向particle_t 类型的结构体。

在此理解的基础上,我修改了您的原始代码,并在必要时在代码本身中提供了适当的注释。但是,如果我误解了您的问题,请告诉我,我会相应地更新答案。

#include<stdio.h>
#include<stdlib.h>

typedef struct {
    double vx;
} particle_t;

typedef struct {
    int m;
    int n;
    particle_t **inparticles;    // inparticles is a pointer to (array of 
                                // pointers to inparticle)
    int size; // max number of particles in the grid
} grid_t;

grid_t *new_grid(int size) { // A helper function to create grid
    grid_t *grid = (grid_t*)malloc(sizeof(grid_t));
    grid->inparticles = (particle_t**)malloc(sizeof(particle_t*));

    if(grid == NULL || grid->inparticles == NULL) return NULL;

    grid->size = size;

    for(int i=0;i<size;++i) {
        grid->inparticles[i] = (particle_t*)malloc(sizeof(particle_t));
        if(grid->inparticles[i] == NULL) {
            return NULL;
        }
    }

    return grid;
}
int main() {
    particle_t *particles = (particle_t*)malloc( 3 * sizeof(particle_t) );

    //create a new grid which can contain multiple particles --- Use a for 
    //loop for creating multiple grids 
    grid_t *grid = new_grid(3);

    if( particles==NULL || grid==NULL ){
        puts("Unable to allocate memory");
        exit(1);
    }

    grid->inparticles[0] = &particles[0];
    grid->inparticles[1] = &particles[1];
    grid->inparticles[2] = &particles[2];

    return 0;
}

答案 4 :(得分:1)

当事情变得复杂时,分而治之是最好的方法。

在堆上创建一个 Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. Hello, world. 类型的结构数组:

particle_t

在堆上创建一个 particle_t* partAddr = malloc(sizeof(particle_t) * numParticles); 类型的结构数组:

grid_t

使 grid_t* gridAddr = malloc(sizeof(grid_t) * numGrids); 类型数组的一个元素指向已分配的 grid_t 类型元素:

particle_t

给网格第一个元素数组的第一个元素的vx字段赋值:

gridAddr[n].inparticles = partAddr;

一切都在一起(其中粒子的数量可能会有所不同):

grid[0].inparticles[0].vx= 3;