Инициализация и использование членов структуры внутри другой структуры - PullRequest
0 голосов
/ 19 июня 2019

Мне нужно использовать ранее объявленную структуру struct (struct1) внутри новой структуры struct (struct2). Также я хочу инициализировать его и использовать некоторые члены struct1 для инициализации других членов struct2.

В частности, я хочу установить значения для struct1 и использовать некоторые из этих значений для определения размеров других членов struct2

Я пробовал то, что показано в коде, но не понимаю, почему оно не работает.

typedef struct ytxModule{
    uint8_t nEncoders;
    uint8_t nDigital;
    uint8_t nAnalog;
    uint8_t nLedsPerControl;
};

typedef struct{
    ytxModule components = {4, 0, 0, 16};

    // encoder pin connections to MCP23S17
    uint8_t encPins[components.nEncoders][2] = {
      {1, 0},  
      {4, 3},   
      {14, 15},  
      {11, 12}   
    };
    // buttons on each encoder
    uint8_t encSwitchPins[components.nEncoders] = { 2, 5, 13, 10 }; 

}ytxE41Module;

Я получаю сообщение об ошибке:

sketch\headers/modules.h:52:37: error: invalid use of non-static data member '<anonymous struct>::components'

  ytxModule components = {4, 0, 0, 16};

                                     ^

sketch\headers/modules.h:55:18: error: from this location

  uint8_t encPins[components.nEncoders][2] = {

Любая помощь будет оценена :)

Ответы [ 2 ]

2 голосов
/ 20 июня 2019

Минимально необходимые изменения

Вы не можете смешивать typedef с инициализаторами - по крайней мере, не в C. У вас также не может быть типов структур, размер которых изменяется в зависимости от данных в структуре - по крайней мере, без их использования ( и только один) элемент гибкого массива (FAM), но ваш код пытается использовать два переменных массива (поэтому они не могут быть FAM).

Вам нужно что-то похожее на:

typedef struct ytxModule{
    uint8_t nEncoders;
    uint8_t nDigital;
    uint8_t nAnalog;
    uint8_t nLedsPerControl;
} ytxModule;  // Add name for typedef

typedef struct{
    ytxModule components;
    uint8_t encPins[4][2];
    uint8_t encSwitchPins[4]; 
} ytxE41Module;

ytxE41Module module = {
    .components = {4, 0, 0, 16},
    .encPins = {
      {1, 0},  
      {4, 3},   
      {14, 15},  
      {11, 12}   
    },
    .encSwitchPins = { 2, 5, 13, 10 },
}; 

Это не изменит форму, если вы инициализируете .components.nEncoders значением, отличным от 4. В зависимости от ваших потребностей, вы можете подумать о замене жестко запрограммированного 4 изменяемым значением во время компиляции, но вам также понадобится способ изменить размеры массивов инициализатора, чтобы они соответствовали, что в лучшем случае, вероятно, было бы непростым, непостижимым в худшем случае. Не ясно, как устанавливаются значения инициализатора.

Использование члена гибкого массива

Если вы хотите использовать член гибкого массива, вам придется организовать тип для хранения массива данных encSwitchPins и encPins и использовать разные обозначения для доступа к элементам FAM.

typedef struct ytxModule{
    uint8_t nEncoders;
    uint8_t nDigital;
    uint8_t nAnalog;
    uint8_t nLedsPerControl;
} ytxModule;

typedef struct
{
    ytxModule components;
    struct
    {
        uint8_t encPins[2];
        uint8_t encSwitchPins;
    } pins[]; 
} ytxE41Module;

Вы больше не можете использовать инициализатор для этого типа данных; вы будете динамически распределять память, а затем назначать значения выделенным данным:

// Data used for initializing structure
int n_pins = 4;
uint8_t encPins[][2] = {
    {  1,  0 },  
    {  4,  3 },   
    { 14, 15 },  
    { 11, 12 },   
};
uint8_t switchPins[] = { 2, 5, 13, 10 };

// Allocate and check allocation
ytxE41Module *mp = malloc(sizeof(*mp) + n_pins * sizeof(mp->pins[0]));
if (mp == NULL)
    return NULL;

// Assign values to allocated structure
mp->components = (ytxModule){ n_pins, 0, 0, 16};
for (int i = 0; i < n_pins; i++)
{
    for (int j = 0; j < 2; j++)
        mp->pins[i].encPins[j] = encPins[i][j];
    mp->pins[i].encSwitchPins = switchPins[i];
}

Если вы пометите тип встроенной структуры, вы можете инициализировать массив этого типа и использовать memmove() (или memcpy()), чтобы переместить копию отдельного массива в структуру FAM. И т. Д. Гораздо проще, если объем данных в структуре фиксирован (например, в 4 элементах массива), как показано в первой части ответа.

0 голосов
/ 29 июня 2019

У меня есть еще один вопрос, что если я захочу инициализировать массив ytxE41Module ?? Я думаю, что компилятору это не нравится:

ytxE41Module e41module[8] = {
    .components = {4, 0, 0, 16},
    .nextAddressPin = {6, 7, 8},
    .encPins = {
      {1, 0},  
      {4, 3},   
      {14, 15},  
      {11, 12}   
    },
    .encSwitchPins = { 2, 5, 13, 10 },
    .orientation = HORIZONTAL,
}; 

И я тоже:)

Есть ли способ сохранить его таким, или мне обязательно нужно использовать динамическое распределение?

Спасибо!

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