Как передать 2 разные структуры с одинаковыми именованными элементами в одну функцию? - PullRequest
0 голосов
/ 12 февраля 2020

Я объявил две структуры с одинаковыми именованными элементами, например:

struct sParametersUdc
{

    float PI;
    float C1;
    float C2;
    float error_old;
    float imin;
    float imax;
};

struct sParametersD
{

    float PI;
    float C1;
    float C2;
    float error_old;
    float imin;
    float imax;
};

EXTERN struct sParametersPll parameterspll;
EXTERN struct sParametersUdc parametersudc;

И теперь у меня вопрос, возможно ли создать одну функцию, которую я мог бы использовать с обеими структурами? Я попробовал решение ниже, но оно не работает, потому что не может найти другую структуру.

void regulator(struct sParametersUdc *udc, float error);

void regulator(struct sParametersUdc *udc, float error)
{   

    (udc->PI)+= (udc->C1)*error + (udc->C2)*(udc->error_old);


    if(udc->PI > udc->imax)  udc->PI = udc->imax;
    if(udc->PI < udc->imin)  udc->PI = udc->imin;

    udc->error_old = error;

}

regulator(&parametersudc, error_udc);

regulator(&parametersd, error_d);

Ответы [ 3 ]

1 голос
/ 12 февраля 2020

Нельзя использовать одну функцию с двумя различными структурами. В C вы должны определить 2 различные функции или изменить свою структуру следующим образом:

struct sParameters
{
float PI;
float C1;
float C2;
float error_old;
float imin;
float imax;
};

struct sParametersD
{
    struct sParameters sp;
};

struct sParametersUdc
{
    struct sParameters sp;
};

void regulator(struct sParameters *sp, float error)
{   

    (sp->PI)+= (sp->C1)*error + (sp->C2)*(sp->error_old);

    if(sp->PI > sp->imax)  sp->PI = sp->imax;
    if(sp->PI < sp->imin)  sp->PI = sp->imin;

    sp->error_old = error;
}

Теперь вы можете вызывать вот так

regulator(&parametersudc.sp, error_udc);
regulator(&parametersd.sp, error_d);
0 голосов
/ 12 февраля 2020

Вы можете создать объединение обеих структур. From C11 6.5.2.3p6 :

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

Предполагая, что обе структуры имеют "общую начальную последовательность", ie. Имея совместимые типы для начальных членов, вы можете получить доступ к одному из них с помощью другого.

struct sParametersUdc {
    float PI;
    float C1;
    float C2;
    float error_old;
    float imin;
    float imax;
};

struct sParametersD {
    float PI;
    float C1;
    float C2;
    float error_old;
    float imin;
    float imax;
};

union sParameters {
    struct sParametersUdc udc;
    struct sParametersD d;
};

void regulator(union sParameters *param, float error)
{   
    struct sParametersUdc *udc = &param->udc;
    udc->PI += udc->C1 * error 
        + udc->C2 * udc->error_old;

    if (udc->PI > udc->imax) {
        udc->PI = udc->imax;
    }
    if (udc->PI < udc->imin)  {
        udc->PI = udc->imin;
    }

    udc->error_old = error;
}

int main() {
    struct sParametersUdc udc;
    regulator(&(union sParameters){ .udc = udc }, 1.0);
    struct sParametersD d;
    regulator(&(union sParameters){ .d = d }, 1.0);
}

Подобные действия могут быть полезны в некоторых случаях, но я думаю, что здесь они служат только уловкой и снижают качество кода. Из того, что вы показали, это похоже на расчет выходного сигнала от интегральной части ПИД-регулятора. Я считаю, что ваш код должен просто создать единую структуру для представления этого «объекта» из обеих структур и одну функцию для его обработки, как в ответе @idris.

0 голосов
/ 12 февраля 2020

Создайте объединение с двумя структурами в нем.

union foo {
sParametersD D;
sParametersUdc Udc;
}

Затем передайте это функции.

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