2010-12-14 3 views
-1

Ich habe gerade angefangen, an einem c-Projekt zu arbeiten. Benötigen Sie Hilfe bei der Übergabe von Funktionszeigern/Makrofunktionen/etc. Ich bin ein php & Python OO Typ, aber neu zu c. Ich habe versucht, das Beispiel für diesen Beitrag zu verallgemeinern. Ich habe eine Main.c mit einer Lib für den Axon-Mikrocontroller, mit dem ich arbeite. Funktioniert wie ein Zauber mit allem in main.c. Ich muss einige der Funktionalität aus dem Haupt in mehr organisierte lib-Dateien verschieben, wenn mein Code wächst. Der Basis-Mikrocontroller lib erzeugt eine Makrofunktion, die es mir ermöglicht, Daten an den Mikrocontroller zu senden, um einen Servo nach links oder rechts zu bewegen. Ich muss jetzt eine servo-spezifische Datei (HS-422.c) erstellen, die es mir erlaubt, Referenzen/Zeiger (?) An eine generische Funktion zu übergeben, die für jedes Servo ausgeführt wird, um die Code-Duplizierung zu erleichtern.Übergeben von Funktionszeigern & int-Referenzen auf eine andere Funktion

Denken Sie daran, ich bin nur darauf konzentriert, Makros/Funktionen/Variablen Verweise auf andere Funktionen zu übergeben und sie aufgerufen/gesetzt haben. Die anderen Grundlagen von c verstehe ich. Ich muss 100 verschiedene Wege ausprobiert haben, um das heute ohne Erfolg zu schaffen. Also, ich habe gerade eine vereinfachte Version geschrieben, in der Hoffnung, dass du eine Idee davon bekommst, was ich versuche.

Vielen Dank für Ihre Hilfe!

/* 
* 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

Diese # definieren sehen sehr skizzenhaft aus! – leppie

+1

C hat kein Konzept von "Referenzen". Die einzige Alternative zur Wertübergabe besteht darin, einen Zeiger zu übergeben. –

+0

Die #define war nur ein Beispiel .. Ich weiß, dass es nicht funktioniert. Ich hoffe, den richtigen Weg zu finden. Und ich bedauere, ich wollte klar auf die Referenzen. Diese waren für Variablen gedacht, also konnte ich die Servo # _Location-Werte in der aufgerufenen turn_servo-Funktion setzen. – pringlized

Antwort

1

Ich habe den Hauptpunkt Ihres Codes ausgewählt und habe diesen Code unten. Sie können Ihre #define in Ihrem ursprünglichen Code ändern.
Bitte sehen Sie den Code unten: (Sie können dies auch laufen kann)

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); 
} 

Ihre turn_servo() Funktion wird nun zwei Funktionen als Parameter übernehmen (entweder myFunc() oder MyFunc2()).
Holen Sie sich einfach den Hauptpunkt dieses Codes und wenden Sie ihn an. Hoffe, das wird helfen.

+0

myFunc() Funktionen werden Ihrem Servo ähnlich sein (PORTE, 2, Position); Ich hoffe, das wird helfen. –

+0

Ehrfürchtig .. Danke .. Werde dieses erste Ding am Morgen versuchen. – pringlized

2

Es ist nicht wirklich klar, mir genau, was Sie erreichen wollen, aber klar ist, dass Sie das Konzept der Zeiger/Referenzen in C nicht wirklich verstehen - also werde ich versuchen zu klären, und hoffentlich hilft Ihnen das, das zu implementieren, was Sie brauchen.

Erstens gibt es in C keine "Referenz". Die einzige Alternative zur Wertübergabe besteht darin, einen Zeiger zu übergeben. Ein Zeiger ist im Grunde nur eine Speicheradresse, und Sie können einen Zeiger (Speicheradresse) auf eine Variable mit dem & (Adresse von) -Operator abrufen. Wenn eine Zeigervariable an eine Funktion, tun Sie so etwas wie die folgenden:

eine Funktion gegeben, die einen Zeiger nimmt:

int foo(int* pointer);

Sie Adresse, um den Speicher zu dieser Funktion einer int Variable würde passieren etwa so:

int x = 10; 
foo(&x); 

so rechts von der Fledermaus, können Sie sehen, dass Ihre Funktionsdefinition oben falsch ist:

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

Dies ist einfach ein Syntaxfehler. Es wird nicht kompiliert, weil der int &currentLocation.&-Operator verwendet wird, um die Adresse einer Variablen zu übernehmen. Es kann nicht in einem Funktionsparameter verwendet werden. Wenn Sie eine „Referenz“ auf currentLocation wollen, müssen Sie in einem Zeiger übergeben, so dass Ihre Funktionsparameter sollten so geschrieben werden:

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

Zweitens, wenn Sie wollen, dass der Wert ändern, auf die der currentLocation Zeiger, Sie müssen den * Operator zu dereference den Zeiger verwenden. Die Zeile, in der Sie currentLocation festlegen, ist nicht korrekt.Was Sie sagen möchte, ist:

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

Und natürlich die Zeile:

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

sein sollte:

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

Beachten Sie, dass Sie in Ihrem ursprünglichen Code verwenden, um die & Betreiber in In beiden Fällen wird die Adresse einer Variablen übernommen. Da currentLocation bereits eine Speicheradresse ist, würde dies dazu führen, dass die Adresse einer Adresse, auch bekannt als ein Zeiger auf einen Zeiger, was sicherlich nicht das ist, was Sie hier wollen.

Schließlich ist der Ausdruck "Zeiger oder Verweis auf das Makro" völlig unsinnig. Ein Makro ist nicht eine Funktion. Es ist mehr wie eine Meta-Funktion: im Wesentlichen ist es eine Vorlage, die von der C preprocessor verwendet wird, um weiteren Quellcode zu generieren. Der C-Präprozessor wird vor der Kompilierungsphase aufgerufen und fungiert im Grunde als Mechanismus zum Suchen/Ersetzen im Quellcode. Sie können kein Zeiger zu einem Makro haben, da Makros in der Kompilierungsphase überhaupt nicht existieren. Sie sind nur für den Präprozessor sinnvoll.

Möglicherweise gibt es hier mehr, aber letztendlich scheint es, dass Sie ein grundsätzliches Missverständnis von Zeigern (und auch Makros) in C haben, und kurz vor der Bereitstellung eines vollständigen Tutorials kann ich nur auf die Syntaxprobleme hinweisen. Ich empfehle Ihnen dringend, lesen Sie eine good introductory book to C, die sicherlich über Zeiger, Makros und Funktionen gehen wird.

+0

Vielen Dank, dass Sie sich die Zeit genommen haben. Sehr geschätzt. Lesen Sie heute eine Vielzahl von Quellen zu Zeigern. Viel zu fassen noch. In kleinen Beispielen experimentiert und sie funktionierten in einer einzigen Datei. Versuche auch zu viel auf einmal zu lösen. Um mein größtes Problem zu extrapolieren, nahm ich das servo() - Makro (lib, mit dem ich arbeite) in main.h und versuchte, einen Zeiger darauf zu bekommen. Ich weiß jetzt, dass das nicht möglich ist. Servo() ist ein Makro zu einem Makro. Ich denke, ich muss in die Core-Bibliothek eintauchen, diese Makros zu ihrem Ursprung umgestalten und einen soliden Basiszeiger neu schreiben. Vielen Dank! – pringlized