C - Окукливать (получать) данные с помощью функции.Лучше всего через ссылку или копию (в среде микроконтроллера)? - PullRequest
0 голосов
/ 05 марта 2019

В настоящее время я программирую 8051 мкС в C (с компилятором: Wickehaeuser µC / 51) и, таким образом, я думаю, какой путь лучше всего, окукливать структуру. В моем текущем случае у меня есть структура времени / даты, которая должна быть скопирована с текущим временем / датой из RTC через SFR.

Итак, я думаю о лучшем способе сделать это:

  • Получить данные через возвращаемое значение, создав переменную внутри функции (get_foo_create)
  • Получить данные по вызову по ссылке (get_foo_by_reference)
  • Получить через вызов по ссылке плюс вернуть его (написав, я думаю, что это глупо, но я тоже думаю об этом) (get_foo_by_reference)

Следующий код является только примером (примечание: в настоящий момент произошла ошибка в последней печати, которая не выводит значение atm)

Какой метод лучше?

typedef struct {
    unsigned char foo;
    unsigned char bar;
    unsigned char baz;
}data_foo;


data_foo get_foo_create(void) {
    data_foo foo;
    foo.bar = 2;
    return foo;
}

void get_foo_by_reference(data_foo *foo) {
    // Read values e.g. from SFR
    foo->bar = 42; // Just simulate SFR
}

data_foo *get_foo_pointer_return(data_foo *foo) {
    // Read values e.g. from SFR
    (*foo).bar = 11; // Just simulate SFR

    return foo;
}


/**
 * Main program
 */
void main(void) {
    data_foo struct_foo;
    data_foo *ptr_foo;

    seri_init(); // Serial Com init
    clear_screen();

    struct_foo = get_foo_create();
    printf("%d\n", struct_foo.bar);

    get_foo_by_reference(&struct_foo);
    printf("%d\n", struct_foo.bar);

    ptr_foo = get_foo_pointer_return(&ptr_foo);
    //Temp problem also here, got 39 instead 11, tried also
    //printf("%d\n",(void*)(*ptr_foo).bar);
    printf("%d\n",(*ptr_foo).bar);


    SYSTEM_HALT; //Programm end
}

1 Ответ

1 голос
/ 05 марта 2019

На 8051 вам следует избегать использования указателей, насколько это возможно.Вместо этого, как правило, лучше - если вы можете себе это позволить - иметь несколько глобальных структур, которые будут управляться различными функциями.Наличие функций для «загрузки thing с адреса» и «сохранения thing для адреса» вместе с различными функциями, которые манипулируют thing, может быть гораздо более эффективным, чем попытка иметь функции, которые могут работать с объектами этого типа »на месте.Я бы также предложил использовать функцию "ldivmod", которая делит 32-битное значение в ldiv_acc на 8-битный аргумент, оставляя частное в ldiv_acc и возвращая остаток, а также функцию "lmul", которая умножает 32-битовое значение в ldiv_acc 8-битным значением.Прошло много времени с тех пор, как я запрограммировал 8051, поэтому я не уверен, какая помощь нужна компиляторам для генерации хорошего кода, но деление и умножение 32x32 будет дорогостоящим по сравнению с использованием комбинации умножений и делений 8x8.

На 8051 код вроде:

uint32_t time;
uint32_t sec,min,hr;

sec = time % 60;
time /= 60;
min = time % 60;
time /= 60;
hr = time % 24;
time /= 24;

, вероятно, будет большим и медленным.Использование что-то вроде:

ldiv_acc.l = time;
sec = ldivmod(60);
min = ldivmod(60);
hr  = ldivmod(24);

может быть намного более компактным и, если вы умным, быстрее.Если скорость действительно важна, вы можете использовать функции для выполнения divmod6, divmod10, divmod24 и divmod60, используя тот факт, что divmod60 (h + 256 * l) равен h * 4 + divmod60 (h * 16 + l),Второе добавление может дать значение больше 256, но если это произойдет, применение того же метода даст операнд ниже 256. Деление unsigned char на другое unsigned char происходит быстрее, чем деление, включающее unsigned int.

...