首页 文章

每个包含动态数组的结构数组

提问于
浏览
2

我对C有点精通,我觉得我的指针都搞清楚了,直到遇到这个问题 . 我正在创建一个数组实现的结构堆栈 . 很容易,但是当我的struct包含动态分配的数组时,我遇到了问题 .

结构是:

typedef struct state {
    int* S;
    double prob;
} state_t;

现在说我想创建一个包含10个结构的数组,每个结构都有一个整数数组,比如5个整数 . 我可以将该数组分配为:

state_t *newContents;
newContents = (state_t *)malloc((sizeof(state_t) + 5 * sizeof(int)) * 10);

我可以在第一个插槽中创建一个结构:

state_t *root = malloc(sizeof *root + 5 * sizeof(int));
root->prob = 1.0;
root->S[0] = 3;
root->S[1] = 5;
root->S[2] = 7;
root->S[3] = 2;
root->S[4] = 0;
newContents[0] = *root;

但是当我尝试添加第二个结构时,Seg错误 . 这是因为数组索引的方式是没有int数组的struct的大小,这意味着每个条目的长度为16个字节 - 对于指针的double 8,为8 . 我希望它代之以28 - 8为双,而4 * 5为整数 . 有没有人知道正确访问此数组元素的方法?

谢谢!

3 回答

  • 1

    你分配你的结构是错误的 . struct本身与其动态分配的数组是分开的,需要单独分配:

    // Allocate the structs.
    state_t *newContents = malloc(10*sizeof(*newContents));
    
    // Allocate the S array of the first struct.
    newContents[0].S = malloc(5*sizeof(int));
    newContents[0].S[0] = 3;
    ...
    

    如果你想要一个实际包含运行时确定长度数组的结构,而不是像当前结构那样指向一个结构,那么你需要一个灵活的数组成员:

    struct state_t {
        double prob;
        int S[]; // No length specified!
    };
    

    然后你可以 malloc(sizeof(state_t) + n*sizeof(int)) 并实际获得一个连续的内存块,其中struct和它的数组在一起 . 但是,如果执行此操作,则无法正确生成 state_t 数组,因为编译器不知道一个结构的结束位置和另一个结构的开始位置 .

  • 2

    做这个:

    state_t *newContents;
    newContents = malloc(sizeof(state_t)*10);
    
    int i;
    for (i=0;i<10;i++)
       (newContents+i)->S=malloc(5 * sizeof(int));
    

    如果希望 newContents 是大小为10的结构数组,那么它应该分配大小等于 sizeof(state_t)*10 . 应明确分配每个结构中的 int * .

  • 4

    运用

    你可以或多或少得到你想要的东西 .

    这是我的测试程序(用 gcc -std=c99 编译):

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct state {
        double prob;
        int S[];
    } state_t;
    
    int main(void) {
        size_t stateSize;
        state_t *newContents;
        stateSize = sizeof(state_t) + 5*sizeof(int);
        newContents = malloc(stateSize * 10);
    
        for (int i = 0; i < 10; i++) {
            state_t *state = (state_t *)((char *)newContents + i * stateSize);
            state->prob = i;
            for (int j = 0; j < 5; j++) {
                state->S[j] = i * j;
            }
        }
    
        for (int i = 0; i < 10; i++) {
            state_t *state = (state_t *)((char *)newContents + i * stateSize);
            printf("[%d] prob: %f\n", i, state->prob);
            for (int j = 0; j < 5; j++) {
                printf("\tS[%d]: %d\n", j, state->S[j]);
            }
        }
    }
    

    跑:

    $ ./a.out 
    [0] prob: 0.000000
        S[0]: 0
        S[1]: 0
        S[2]: 0
        S[3]: 0
        S[4]: 0
    [1] prob: 1.000000
        S[0]: 0
        S[1]: 1
        S[2]: 2
        S[3]: 3
        S[4]: 4
    [2] prob: 2.000000
        S[0]: 0
        S[1]: 2
        S[2]: 4
        S[3]: 6
        S[4]: 8
    [3] prob: 3.000000
        S[0]: 0
        S[1]: 3
        S[2]: 6
        S[3]: 9
        S[4]: 12
    [4] prob: 4.000000
        S[0]: 0
        S[1]: 4
        S[2]: 8
        S[3]: 12
        S[4]: 16
    [5] prob: 5.000000
        S[0]: 0
        S[1]: 5
        S[2]: 10
        S[3]: 15
        S[4]: 20
    [6] prob: 6.000000
        S[0]: 0
        S[1]: 6
        S[2]: 12
        S[3]: 18
        S[4]: 24
    [7] prob: 7.000000
        S[0]: 0
        S[1]: 7
        S[2]: 14
        S[3]: 21
        S[4]: 28
    [8] prob: 8.000000
        S[0]: 0
        S[1]: 8
        S[2]: 16
        S[3]: 24
        S[4]: 32
    [9] prob: 9.000000
        S[0]: 0
        S[1]: 9
        S[2]: 18
        S[3]: 27
        S[4]: 36
    

相关问题