Передача указателей на функции и ссылки на int на другую функцию - PullRequest
0 голосов
/ 14 декабря 2010

Только начал работать над проектом c. Нужна помощь с передачей указателей на функции / макрофункций / и т.д. Я парень из php & python OO, но новичок в c. Я попытался обобщить пример для этого поста. У меня есть main.c с библиотекой для микроконтроллера Axon, с которым я работаю. Работает как шарм со всем в main.c. Мне нужно переместить некоторые функциональные возможности из основных в более организованные файлы lib по мере роста моего кода. Базовая библиотека микроконтроллеров создает макрофункцию, которая позволяет мне отправлять данные в микроконтроллер для перемещения сервопривода влево или вправо. Теперь мне нужно создать файл для сервомотора (HS-422.c), который позволит мне передавать ссылки / указатели (?) На общую функцию, которая будет выполняться для каждого сервомотора, чтобы облегчить дублирование кода.

Имейте в виду, что я сосредоточен только на передаче ссылок на макросы / функции / переменные другим функциям и их вызове / установке. Другие основы c я понимаю. Должно быть, я попробовал 100 различных способов сделать эту работу сегодня без удачи. Поэтому просто написал упрощенную версию, надеясь, что вы поймете, что я пытаюсь сделать.

Спасибо за помощь!

/*
 * main.h 
 * I'm trying to make a pointer or reference to the macro.  
 * The original file had:
 * #define servo1(position) servo(PORTE,2,position); 
 */

 // servo is a macro defined in another microcontroller file
 #define (void)(*servo1)(position) servo(PORTE,2,position); 
 #define (void)(*servo2)(position) servo(PORTE,3,position); 


/* main.c */

// init main functions
void servo_scan(void);

// init vars
int servo1_location = 0;
int servo2_location = 0;

int main(void)
{
  for(;;)
  {
     servo_turn();
  }
}

// get the servos to turn
void servo_turn(void)
{
  turn_servo( *servo1, &servo1_location, 200);
  turn_servo( *servo2, &servo2_location, 950);
}


/* HS-422.c */
void turn_servo(void (*servo)(int position), int &currentLocation, int newLocation)
{
  // turning
  for(uint16_t  i=&currentLocation; i<newLocation; i=i+10)
  {
    // turn servo
    // hoping the specifc passed servo# pointer gets called
    *servo(i);     

    // set value by reference to origional servo#_location var. making sure.
    &currentLocation = i; 

    // pause
    delay_ms(20);
  }
}

Ответы [ 2 ]

2 голосов
/ 14 декабря 2010

Мне не совсем понятно, чего именно вы пытаетесь достичь, но ясно, что вы не совсем понимаете концепцию указателей / ссылок в C - поэтому я постараюсь уточнить, и, надеюсь, чтопоможет вам реализовать то, что вам нужно.

Во-первых, в Си нет такого понятия, как «ссылка». Единственная альтернатива передаче по значению - это передача указателя.Указатель - это просто адрес памяти, и вы можете получить указатель (адрес памяти) на переменную, используя оператор & (address of).Передавая переменную-указатель в функцию, вы делаете что-то вроде следующего:

Дана функция, которая принимает указатель:

int foo(int* pointer);

Вы передадите памятьадрес переменной int для этой функции, например, так:

int x = 10;
foo(&x);

Итак, сразу видно, что приведенное выше определение функции неверно:

void turn_servo(void (*servo)(int position), int &currentLocation, int newLocation);

Этопросто синтаксическая ошибка.Он не скомпилируется, потому что int &currentLocation. Оператор & используется для получения адреса переменной.Его нельзя использовать в параметре функции.Если вам нужна «ссылка» на currentLocation, вам нужно передать указатель, поэтому параметры вашей функции должны быть записаны в виде:

void turn_servo(void (*servo)(int position), int* currentLocation, int newLocation);

Во-вторых, когда вы хотите изменить значение, на которое указываетуказатель currentLocation, вам нужно использовать оператор *, чтобы разыменовать указатель.Таким образом, строка, где вы устанавливаете currentLocation, неверна.То, что вы хотите сказать, это:

// set value by to origional servo#_location var. making sure.
*currentLocation = i; 

И, конечно, строка:

  for(uint16_t i=&currentLocation; i<newLocation; i=i+10)

должна быть:

  for(uint16_t i= *currentLocation; i<newLocation; i=i+10)

Обратите внимание, что в исходном кодев обоих случаях вы используете оператор &, который принимает адрес переменной.Поскольку currentLocation уже является адресом памяти, это может привести к получению адреса адреса , также известного как указатель на указатель, что, безусловно, не то, что вам нужно.

Наконец, фраза «указатель или ссылка на макрос» совершенно бессмысленна.Макрос является , а не функцией.Это больше похоже на мета-функцию: по сути это шаблон, используемый препроцессором C для генерации дополнительного исходного кода.Препроцессор C вызывается перед фазой компиляции и в основном действует как механизм поиска / замены в исходном коде.Вы не можете иметь указатель на макрос, потому что для всех намерений и целей макросы даже не существуют на этапе компиляции.Они имеют значение только для препроцессора.

Здесь может быть что-то еще, но в конечном итоге у вас, похоже, есть фундаментальное недопонимание указателей (а также макросов) в C, и не хватает полного учебника, лучшегоЯ могу сделать, это указать на проблемы синтаксиса.Я настоятельно рекомендую вам прочитать хорошую вводную книгу по C , в которой наверняка будут рассмотрены указатели, макросы и функции.

1 голос
/ 14 декабря 2010

Я выбрал суть вашего кода, и у меня есть этот код ниже.
Возможно, вы захотите изменить #define в своем исходном коде.
Пожалуйста, посмотрите код ниже: (вы также можете запустить это)

void myFunc(int pos);
void myFunc2(int pos);

int main (int argc, const char * argv[]) {


    typedef void (*pFunc)(int);
    pFunc pfArr[2];
    pfArr[0] = &myFunc;
    pfArr[1] = &myFunc2;


    int x = 3;
    int newLoc = 4;
    turn_servo(pfArr[1], x, newLoc);
    turn_servo(pfArr[0], x, newLoc);


    return 0;
}



void turn_servo(void (*servo)(int position), int currentLocation, int newLocation)
{
    printf("\nturn_servo starts");
    printf("\nturn_servo currentLocation: %d", currentLocation);
    printf("\nturn_servo newLocation: %d", newLocation);
    servo(1);

}

void myFunc(int pos)
{
    printf("\nmyFunc starts");
    printf("\nmyFunc pos: %d", pos);
}

void myFunc2(int pos)
{
    printf("\nmyFunc2 starts");
    printf("\nmyFunc2 pos: %d", pos);
}

Ваша функция turn_servo () теперь будет принимать две функции в качестве параметра (myFunc () или myFunc2 ()).
Просто получите основную точку этого кода и примените его.Надеюсь, это поможет.

...