Κάθε πρόγραμμα σε C αποτελείται από συναρτήσεις, που μπορούμε να τις βρούμε σε έτοιμες βιβλιοθήκες τις οποίες εισάγουμε στο πρόγραμμα μας ή να να γράψουμε τις συναρτήσεις μας στο πρόγραμμα μας. Πρέπει να προσέξουμε ότι, σε κάθε πρόγραμμα είναι υποχρεωτική η συνάρτηση main(), όπου από εκεί αρχίζει η εκτέλεση του προγράμματος μας.
Οι συναρτήσεις βοηθούν τον προγραμματιστή να «τεμαχίζει» μεγάλα προγράμματα σε μικρότερα τμήματα, όπου καθένα εκτελεί μια συγκεκριμένη λειτουργία. Μια συνάρτηση εκτελείται μόνο όταν κληθεί από κάποια άλλη συνάρτηση. Η μόνη εξαίρεση είναι η συνάρτηση main() που εκτελείται αυτόματα.
Μια συνάρτηση στη C μπορεί να επιστρέψει μια τιμή. Ορίζουμε σαν τύπο της συνάρτησης, σαν τον τύπο δεδομένων που επιστρέφει. Έτσι για παράδειγμα, ο τύπος μιας συνάρτησης μπορεί να είναι int, float κ.τ.λ. αν ο επιστρεφόμενος τύπος δεδομένων είναι int, float κ.τ.λ. αντίστοιχα. Μια συνάρτηση μπορεί να μην επιστρέφει κάποια τιμή, οπότε θα πρέπει να δηλωθεί με τον τύπο void.
Μια συνάρτηση μπορεί να έχει καμία, μια ή περισσότερες παραμέτρους μέσω των οποίων ο κώδικας που την καλεί μπορεί να της μεταβιβάσει δεδομένα. Οι παράμετροι μιας συνάρτησης, αποτελούν τοπικές μεταβλητές της συνάρτησης.
Οι μεταβλητές που δηλώνονται μόνο μέσα στο σώμα μιας συνάρτησης αποτελούν και αυτές τοπικές μεταβλητές και έχουν εμβέλεια μέσα σ’ αυτή τη συνάρτηση. Οι τοπικές μεταβλητές μπορούν να χρησιμοποιηθούν μόνο από τη συνάρτηση στην οποία δηλώνονται και είναι άγνωστες έξω από αυτήν.
Συναρτήσεις χωρίς παραμέτρους
Παράδειγμα Α: Η παρακάτω συνάρτηση εμφανίζει τους αριθμούς 0 έως 32 στην πόρτα C ενός μικροελεγκτή AVR. Δεν επιστρέφει καμία τιμή και γι’ αυτό δηλώνεται ως void. Δεν διαθέτει καμία παράμετρο και έτσι κάθε φορά που καλείται κάνει την ίδια λειτουργία.
void print_f(void)
{
DDRC = 0xFF;
int i;
for(i=0; i<=32; i++) PORTC = i;
}
int main(void)
{
print_f();
print_f();
while(1);
}
Η συνάρτηση main() καλεί την συνάρτηση print_f() δυο φορές, η οποία εμφανίζει τους ίδιους αριθμούς. Επειδή αυτή δεν έχει παραμέτρους, δεν υπάρχει τρόπος να επέμβουμε στην λειτουργία της.
Κατά τον ορισμό μιας συνάρτησης που δεν έχει παραμέτρους, δηλώνουμε τον τύπο void μέσα στις παρενθέσεις μετά το όνομα της συνάρτησης.
Συναρτήσεις με παραμέτρους
Οι παράμετροι είναι ένας τρόπος με τον οποίο ένα τμήμα προγράμματος μεταβιβάζει δεδομένα σε μια συνάρτηση.
Παράδειγμα Β: Η παρακάτω συνάρτηση είναι μια τροποποίηση του προηγούμενου παραδείγματος, η οποία διαθέτει δυο παραμέτρους που της δίνει την δυνατότητα ο κώδικας που την καλεί να ορίζει το εύρος τιμών που θα δώσει στην PORTC. Η συνάρτηση χρησιμοποιεί τις παραμέτρους start και stop για να ορίσει το εύρος των τιμών.
void print_f(int start, int stop)
{
DDRC = 0xFF;
int i;
for(i=start; i<=stop; i++) PORTC = i;
}
int main()
{
print_f(2, 16);
print_f(32, 128);
while(1);
}
Παράδειγμα Γ: Στο ακόλουθο πρόγραμμα, η συνάρτηση mesosoros() έχει δυο παραμέτρους τύπου int, μέσων των οποίων ο κώδικας που την καλεί της μεταβιβάζει δεδομένα και επιστρέφει μια τιμή.
Η συνάρτηση mesosoros() χρησιμοποιεί τρεις τοπικές μεταβλητές και συγκεκριμένα τις παραμέτρους a και b και τη μεταβλητή m που δηλώνεται μέσα στη συνάρτηση. Οι τοπικές μεταβλητές μπορούν να χρησιμοποιηθούν μόνο από τον κώδικα της συνάρτησης που δηλώνονται και είναι άγνωστες έξω από αυτήν.
Η συνάρτηση mesosoros() επιστρέφει μια τιμή τύπου int και στη συνέχεια πηγαίνει πίσω στο σημείο του προγράμματος που την κάλεσε. Η τιμή που επιστρέφει πρέπει να είναι του ίδιου τύπου με τον τύπο της συνάρτησης.
Συναρτήσεις που επιστρέφουν μια τιμή
Μια συνάρτηση επιστρέφει μια τιμή στο πρόγραμμα που την κάλεσε μέσω της εντολής return, με την ακόλουθη σύνταξη: return (παράσταση); ή return παράσταση; Η εντολή return τερματίζει την συνάρτηση και επιστρέφει ως τιμή το αποτέλεσμα της παράστασης που ορίζεται στην εντολή return. Αν σε μια συνάρτηση δεν υπάρχει εντολή return, η συνάρτηση επιστρέφει τον έλεγχο μόλις εκτελέσει την τελευταία της πρόταση, χωρίς να επιστρέψει κάποια τιμή. Αν μια συνάρτηση δηλώνεται ως void τότε μπορεί να τερματιστεί με μια εντολή return χωρίς τιμή επιστροφής.
uint8_t mesosoros(uint8_t a, uint8_t b)
{
uint8_t m;
m = (a+b)/2;
return m;
}
int main(void)
{
DDRC = 0xFF;
uint8_t k;
k = mesosoros(6, 10);
PORTC = k;
while(1);
}
Όταν ένα πρόγραμμα συναντήσει μια συνάρτηση και την καλέσει, θα πρέπει να γνωρίζει τον τύπο της. Όταν μια συνάρτηση καλείται πριν τον ορισμό της, τότε ο μεταγλωττιστής δεν γνωρίζει τον τύπο της αλλά ούτε τον τύπο των παραμέτρων της και τότε ο μεταγλωττιστής θα προβάλει μήνυμα σφάλματος.
Συνήθως οι συναρτήσεις δηλώνονται μετά την συνάρτηση main() και με αυτό τον τρόπο ο μεταγλωττιστής θα καλέσει μια συνάρτηση πριν τον ορισμό της, με αποτέλεσμα να προβάλει μήνυμα σφάλματος. Για να λύσουμε αυτό το πρόβλημα, δηλώνουμε μια συνάρτηση πριν την χρησιμοποιήσουμε.
Στη δήλωση μιας συνάρτησης ορίζεται ο τύπος της, το όνομα της και οι παράμετροι της. Η δήλωση αυτή ονομάζεται «πρωτότυπο» της συνάρτησης και γίνεται σε σημείο πριν από την κλήση της. Μια συνάρτηση που το πρωτότυπο της ορίζεται πριν από την main() καθώς και πριν από κάθε συνάρτηση που την καλεί, η υλοποίηση της μπορεί να γίνει μετά από την main().
Παράδειγμα Δ: Στο παρακάτω πρόγραμμα η συνάρτηση add() δηλώνεται (δηλ. ορίζεται το πρωτότυπο της) πριν από την main() και υλοποιείται μετά από αυτή.
uint8_t add(uint8_t a, uint8_t b);
int main(void)
{
DDRC = 0xFF;
DDRA = 0x00;
DDRB = 0x00;
uint8_t x, y, s;
x = PINA;
y = PINB;
s = add(x, y);
PORTC = c;
while(1);
}
uint8_t add(uint8_t a, uint8_t b)
{
uint8_t s;
s = a + b;
return s;
}
Παράδειγμα Ε: Μια συνάρτηση η οποία υλοποιείται πριν από την main() καθώς και πριν από κάθε συνάρτηση που την καλεί, δεν χρειάζεται να δηλωθεί με το πρωτότυπο της. Σε αυτή την περίπτωση μπορούμε να ξαναγράψουμε το πρόγραμμα του προηγούμενου παραδείγματος ως εξής:
uint8_t add(uint8_t a, uint8_t b)
{
uint8_t s;
s = a + b;
return s;
}
int main(void)
{
DDRC = 0xFF;
DDRA = 0x00;
DDRB = 0x00;
uint8_t x, y, s;
x = PINA;
y = PINB;
s = add(x, y);
PORTC = c;
while(1);
}
Αν μια συνάρτηση έχει παραμέτρους αυτές δηλώνονται με τον τύπο τους μετά το όνομα της συνάρτησης μέσα στις παρενθέσεις που ακολουθούν.
Οι παράμετροι μιας συνάρτησης χρησιμοποιούνται για την μεταβίβαση δεδομένων από το πρόγραμμα προς τη συνάρτηση την οποία καλεί. Οι τιμές με τις οποίες καλείται μια συνάρτηση λέγονται ορίσματα της συνάρτησης.
Στο προηγούμενο πρόγραμμα η συνάρτηση add ορίζεται με δυο παραμέτρους τις a και b. Η συνάρτηση main() καλεί την συνάρτηση add() με τον ακόλουθο τρόπο: s = add(x,y);
Οι τιμές των ορισμάτων x και y αντιγράφονται στις παραμέτρους a και b της συνάρτησης add() αντίστοιχα. Αυτός ο τρόπος μεταβίβασης ορισμάτων ονομάζεται μεταβίβαση κατ’ αξία και με αυτό τον τρόπο αντιγράφονται οι τιμές των ορισμάτων στις αντίστοιχες παραμέτρους της συνάρτησης. Κατά συνέπεια η συνάρτηση add() δεν μπορεί να τροποποιήσει τις τιμές των ορισμάτων x και y με τις οποίες κλήθηκε.