Статическая инициализация члена гибкого массива - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь скомпилировать этот кусок кода, и он дает мне ошибку: статическая инициализация элемента гибкого массива.Я знаю, что это потому, что я инициализирую id и timestamp 0, но они должны быть назначены во время выполнения, а 0 - это просто заполнитель до тех пор

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

#include "input.h"

typedef struct Ticket {
    int id;
    long timestamp;
} Ticket;

typedef struct Categories {
    char name[20];
    char code[3];
    Ticket ticket[];
} Category;

void genereateTickets() {
    struct Ticket *ptr;
    int nTickets = getNumTickets();
    ptr = (struct Ticket *)malloc(nTickets * sizeof(struct Ticket));

    for (int i = 0; i < nTickets; i++) {
        (ptr+i)->id = rand() % nTickets;
        (ptr+i)->timestamp = 0;
    }
}

void initializeCategories() {
    Category category1 = { "Academic Registrar", "AR", 0, 0 };
    Category category2 = { "Financial Services", "FS", 0, 0 };
    Category category3 = { "IT Support", "IT", 0, 0 };
    Category category4 = { "Parking Police", "PP", 0, 0 };
    Category category5 = { "Coop Placement", "CP", 0, 0 };
}

Ответы [ 3 ]

0 голосов
/ 19 февраля 2019

Этот код выдает несколько недоразумений о C. Вот, что я предполагаю, чтобы быть исправленной версией, с правками для правописания и стиля:

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

#include "input.h"

typedef struct Ticket {
  int id;
  long timestamp;
} Ticket;

typedef struct Categories {
  char name[20];
  char code[3];
  // One ticket doesn't need an array.
  Ticket ticket;
} Category;

void generateTickets(){
  struct Ticket *ptr;
  int nTickets = getNumTickets();
  ptr = malloc(nTickets * sizeof(struct Ticket));

  for(int i = 0; i < nTickets; i++)
  {
    // rand() % nTickets won't guarantee uniqueness
    ptr[i].id = rand() % nTickets;
    ptr[i].timestamp = 0;
  }
}

void initializeCategories() {
  // Nested initialisation for nested structs.
  Category category1 = {"Academic Registrar", "AR", {0, 0}};
  Category category2 = {"Financial Services", "FS", {0, 0}};
  Category category3 = {"IT Support", "IT", {0, 0}};
  Category category4 = {"Parking Police", "PP", {0, 0}};
  Category category5 = {"Coop Placement", "CP", {0, 0}};
}
0 голосов
/ 19 февраля 2019

Для const структур статической длительности, работоспособный подход в большинстве случаев состоит в том, чтобы объявить структуру, которая имеет те же члены, что и версия FAM, но с гибким элементом массива, замененным массивом подходящего размера, и затем построитьобъединение, которое содержит этот тип, а также объединение с гибким членом массива.Общая начальная последовательность гарантирует, что любой тип может использоваться для проверки общих членов, и если реализация прислушивается к сноске 88 проекта C11 (N1570), в которой говорится, что цель 6.5p7 состоит в том, чтобы указать обстоятельства, когда вещиможет, псевдоним, он будет воздерживаться от использования правила в качестве предлога для взлома такого кода, поскольку ссылки на хранилище, которое никогда не изменяется, никогда не псевдоним (псевдонимы включают ситуации, когда изменение порядка доступа к объекту будет влиять на его семантику; если объектникогда не изменяемый, порядок доступа никогда не будет иметь какого-либо наблюдаемого эффекта).

Теоретически реализация могла бы разместить элемент гибкого массива с другим смещением по сравнению с массивом фиксированного размера, но код мог бы,при желании используйте статическое утверждение, чтобы этого не произошло.Преднамеренно тупая интерпретация может сломать вещи, но, поскольку Правило Одной Программы позволило бы намеренно тупым реализациям сломать практически любую программу, это не говорит о многом.

0 голосов
/ 19 февраля 2019

Вы не можете инициализировать член гибкого массива.Согласно C 2018 6.7.2.1 18, в большинстве случаев, член гибкого массива игнорируется.Это одна из таких ситуаций: При инициализации это так, как если бы элемент не существовал.

Создание структуры с элементом гибкого массива в операторе объявления может создать только структуру с нулевыми элементами в массиве.Чтобы создать структуру с большим количеством членов в массиве, вы должны динамически распределять пространство с помощью malloc или аналогичной процедуры.После того, как вы выделите достаточно места, вы можете преобразовать указатель в указатель в Category и затем присвоить (а не инициализировать) значения его элементам, включая элементы его элемента гибкого массива.

(Возможно,мог бы быть ужасный способ определить объединение, содержащее структуру с элементом гибкого массива, таким образом, чтобы обеспечить достаточное пространство для элементов массива, заполнив объединение массивом char необходимого размера.не удалось инициализировать эти элементы, но вы можете назначить их. Не делайте этого.)

Чтобы настроить прототип Category объектов, вы можете использовать:

static const Category category1 = {"Academic Registrar"};
static const Category category2 = {"Financial Services"};
static const Category category3 = {"IT Support", "IT"};
static const Category category4 = {"Parking Police", "PP"};
static const Category category5 = {"Coop Placement", "CP"};

Позже,чтобы создать Category с несколькими Ticket элементами, вы можете сделать:

Category *C = malloc(sizeof *C + nTickets * sizeof(Ticket));
// Test C for NULL in case malloc failed.

// Copy initial data into new Category.
*C = category3;

// Assign values to Ticket elements.
for (int i = 0; i < nTickets; ++i)
{
    C->ticket[i] = rand();
    C->timestamp = 0;
}

Обратите внимание, что вы не можете создать массив объектов Category, потому что они имеют гибкий размер и объекты в массивеможет иметь только фиксированный размер.Таким образом, вы можете работать только с одним Category одновременно.Указатель C выше может указывать только на один Category, а не на их массив.Но элемент C->ticket является массивом Ticket.

Обратите внимание, что я не обязательно рекомендую копировать данные в Category из прототипов таким образом.Если данные короткие, их можно просто назначить в коде.Если данные длинные, может быть лучше использовать указатели на данные, а не копировать все данные в каждый из них.Хорошие решения зависят от обстоятельств.Приведенный выше код приведен только в качестве примера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...