如何在结构体中使用未指定大小的数组的 malloc。

huangapple go评论52阅读模式
英文:

How to use malloc for an array in struct with unspecified size

问题

我有一个带有未指定大小的数组的结构体。

struct KMData{
    int ndata;
    int dim;
    float **features;
    int *assigns;
    int *labels;
    int nlabels;
};

像这样。

在下面的函数中,我尝试根据给定文件的大小为 features 和 labels 分配内存,但似乎没有分配我指定的数据大小。

struct KMData kmdata_load(char *datafile) {

    ssize_t tokens;
    ssize_t lines;

    filestats(datafile, &tokens, &lines);

    struct KMData *data = malloc(sizeof(struct KMData) + (lines * sizeof(int)) + ((tokens - (2*lines)) * sizeof(float)));
    
    printf("tokens: %zd, lines: %zd\n", tokens, lines);

    data->labels = malloc(lines * sizeof(int));
    data->features = malloc((tokens - (2*lines)) * sizeof(float));

    ssize_t f_size = sizeof(*(data->features));
    printf("features 大小: %zd\n", f_size);

    FILE *fin = fopen(datafile, "r");

    char line[3150];

    int i = 0;

    while (fgets(line, 3150, fin)) {

        data->ndata++;
        char *token = strtok(line, " \t");

        data->labels[data->ndata-1] = atoi(token);

        float feats[(tokens/lines)-2];

        int f = 0;
        token = strtok(NULL, " \t");
        while ((token = strtok(NULL, " \t"))) {
            feats[f] = atof(token);
           
            data->features[data->ndata-1][f] = atof(token);

            if(i==0){
                printf("token %d: %f\n", f, data->features[data->ndata-1][f]);
            }
            f++;
        }
        i++;
        ssize_t size = sizeof(feats)/sizeof(float);
       
    }
    fclose(fin);
    
    return *data;
}

int main(int argc, char* argv[]){
  struct KMData data = kmdata_load(argv[1]);
}

我漏掉了什么吗?

当我打印出 features 的大小时,它显示为 8,比我预期的要小得多。

在阅读了评论和答案后,我尝试了以下操作

struct KMData *data = malloc(sizeof(struct KMData));
data->labels = malloc(lines * sizeof(int));

然后

data->labels[data->ndata-1] = atoi(token);

但它导致了分段错误,所以我仍然没有正确分配数组吗?
英文:

I have a struct with arrays that size are not specified.

struct KMData{
    int ndata;
    int dim;
    float **features;
    int *assigns;
    int *labels;
    int nlabels;
};

like this.

In my function below, I try to malloc the memory for features and labels depending on the size of the given file, but it seems like it is not mallocing the size of the data I specified.

struct KMData kmdata_load(char *datafile) {

    ssize_t tokens;
    ssize_t lines;

    filestats(datafile, &tokens, &lines);

    struct KMData *data = malloc(sizeof(struct KMData) + (lines * sizeof(int)) + ((tokens - (2*lines)) * sizeof(float)));
    
    printf("tokens: %zd, lines: %zd\n", tokens, lines);

    data->labels = malloc(lines * sizeof(int));
    data->features = malloc((tokens - (2*lines)) * sizeof(float));

    ssize_t f_size = sizeof(*(data->features));
    printf("size of features: %zd\n", f_size);

    FILE *fin = fopen(datafile, "r");

    char line[3150];

    int i = 0;

    while (fgets(line, 3150, fin)) {

        data->ndata++;
        char *token = strtok(line, " \t");

        data->labels[data->ndata-1] = atoi(token);

        float feats[(tokens/lines)-2];

        int f = 0;
        token = strtok(NULL, " \t");
        while ((token = strtok(NULL, " \t"))) {
            feats[f] = atof(token);
           
            data->features[data->ndata-1][f] = atof(token);

            if(i==0){
                printf("token %d: %f\n", f, data->features[data->ndata-1][f]);
            }
            f++;
        }
        i++;
        ssize_t size = sizeof(feats)/sizeof(float);
       
    }
    fclose(fin);
    
    return *data;
}

int main(int argc, char* argv[]){
  struct KMData data = kmdata_load(argv[1]);
}

Anything that I missed here?

When I print out the size of features, it gives 8, which is way smaller than what I am expecting.

after reading comments and answers, I tried doing

struct KMData *data = malloc(sizeof(struct KMData));
data->labels = malloc(lines * sizeof(int));

then

data->labels[data->ndata-1] = atoi(token);

but it gives me segmentation fault, so am I still not allocating the array correctly?

答案1

得分: 1

当一个结构体包含指针时,你只为结构体分配空间。这会为指针分配空间,但它们将指向垃圾。

struct KMData *data = malloc(sizeof(struct KMData));

然后你为指针分配空间并将其赋值。

data->labels = malloc(lines * sizeof(int));

当我打印出 features 的大小时,它显示为 8,这比我预期的要小得多。

结构体只存储指针,在现代计算机上通常是 64 位(8 字节)。这就是为什么 sizeof(data->features) 是 8 的原因。你无法获得分配给 data->features 的内存大小。

因为 data->features 是一个 float **,它是一个指针列表。你为指针分配空间,然后将现有的浮点数列表赋给它。使用 sizeof(float*) 乘以你想要存储的列表数量来分配空间。然后分配一个浮点数列表。

// 为每一行分配一个指向浮点数列表的指针的空间。
data->features = malloc(lines * sizeof(float*));

// 为第一行中的每个令牌(一个浮点数)分配空间
data->features[0] = malloc(tokens * sizeof(float));

malloc 不会清除分配的内存,它将包含之前的内容。有时这是0,通常是垃圾。你还必须初始化结构体的任何成员以确保它们被正确设置。

data->ndata = 0;
data->dim = 0;
data->nlabels = 0;
英文:

When a struct contains pointers, you allocate space for just the struct. This will allocate space for the pointers, but they will point at garbage.

struct KMData *data = malloc(sizeof(struct KMData));

Then you allocate space and assign it to the pointers.

data->labels = malloc(lines * sizeof(int));

> When I print out the size of features, it gives 8, which is way smaller than what I am expecting.

The struct only stores the pointer, which on a modern computer is typically 64 bits (8 bytes). That's why sizeof(data->features) is 8. You cannot get the size of the memory allocated to data->features.

Because data->features is a float **, it is a list of pointers. You allocate space for the pointers, then assign existing lists of floats. Allocate with sizeof(float*) times the number of lists you want to store. Then allocate a list of floats.

// Allocate space for a pointer to a list of floats for each line.
data->features = malloc(lines * sizeof(float*));

// Allocate space for each token (a float) in the first line
data->features[0] = malloc(tokens * sizeof(float));

malloc does not clear the allocate memory, it will contain whatever was in it before. Sometimes this is 0, often it is garbage. You also must initialize any members of the struct to be sure.

data->ndata = 0;
data->dim = 0;
data->nlabels = 0;

huangapple
  • 本文由 发表于 2023年4月7日 03:21:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75953047.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定