Доступ к структурам и Calloc

#c #caching #struct #segmentation-fault

#c #кэширование #структура #ошибка сегментации

Вопрос:

Я пытаюсь смоделировать простой кеш. У меня возникла пара проблем. 1) Можно ли сделать длину массива в строке или установить произвольно. Например, с помощью конструктора. 2) При запуске этого кода я получаю ошибку Seg, и я не могу сказать, почему. Я неправильно обращаюсь к массивам?

Заранее благодарю вас.

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

struct Line {
    unsigned int valid;
    unsigned int tag;
}line;

typedef struct Line Line;

struct Set {
    Line lines[5];
}set;

typedef struct Set Set;

struct Cache {
    Set sets[5];
}cache;

typedef struct Cache Cache;

int main(void) {
  Cache *cache = calloc(1,sizeof(Cache));
  
  for(int i=0; i<5; i  ){
        for(int j=0; i<5; j  ){
            cache->sets[i].lines[j].valid = 0;
            cache->sets[i].lines[j].tag = 0;
        }
    }

  free(cache);
}
  

Комментарии:

1. У вас есть опечатка во внутреннем цикле: for (int j = 0; i < 5; j ) { должно быть for (int j = 0; j < 5; j ) { .

2. OT: вы объявляете глобальные переменные с именами line , set , и cache . Я предполагаю, что они вам не нужны. Например, в объявлении for struct Cache следует struct Cache { Set sets[5]; }; отметить, что final cache удаляется.

3. Конечно, после calloc того, как цикл по новому объекту для установки его в 0 является избыточным.

Ответ №1:

Существует два идиоматических способа создания структур переменной длины. Первый:

 struct blah {
    int a, b, c;
    char d, e, f;
    short g;
    MyType x[0];
};
  

Чтобы создать такую структуру, вы должны:

 struct blah *MakeBlah(int n) {
     struct blah *p;
     if ((p = malloc(sizeof *p   sizeof *p->x * n)) != 0) {
          /* whatever */
     }
     return p;
}
  

Другой:

 struct blah {
    int a, b, c;
    char d, e, f;
    short g;
    MyType *x;
};

struct blah *MakeBlah(int n) {
    struct blah *p;
    if ((p = malloc(sizeof *p   sizeof *p->x * n)) != 0) {
         p->x = (MyType *)(p 1);
    }
    return p;
}
  

В обоих случаях, после MakeBlah того, как вы можете свободно заполнить x[0 ..n-1] по своему желанию.

Первый подход немного более аккуратный и может выжить realloc() без вмешательства, тогда как второй подход требует перезагрузки x в случае перераспределения.

Второй подход совместим со всеми версиями C, от реального C вплоть до последней версии стандарта; в то время как первый подход действителен только в некоторых выпусках стандарта и может быть отозван при более позднем выходе из тела стандартов.

Комментарии:

1. Это зависит от стандарта C. Прочитайте о гибких элементах массива — третьем, более современном способе. Для первого случая x[0] становится x[]