我对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个字节 - 对于指针的双精度数为8,为8。我希望它代之以28 - 8为双,而4 * 5为整数。有没有人知道如何正确访问这个数组的元素?
谢谢!
答案 0 :(得分:4)
你的结构错误分配。结构本身与其动态分配的数组是分开的,需要单独分配:
// 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
数组,因为编译器不知道一个结构在哪里结束而另一个结构开始。
答案 1 :(得分: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 *
。
答案 2 :(得分:1)
使用
你可以或多或少得到你想要的东西。
这是我的测试程序(使用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