Μόλις άρχισα να ενδιαφέρομαι για τα περιεχόμενα της στοίβας της κύριας λειτουργίας διεργασίας στο linux. Έκανα μια έρευνα και τώρα σας παρουσιάζω το αποτέλεσμα.

Επιλογές για την περιγραφή της κύριας λειτουργίας:
1. int main()
2. int main (int argc, char **argv)
3. int main(int argc, char **argv, char **env)
4. int main(int argc, char **argv, char **env, ElfW(auxv_t) auxv)
5. int main(int argc, char **argv, char **env, char **μήλο)

Argc - αριθμός παραμέτρων
argv - ένας μηδενικός τερματικός πίνακας δεικτών σε συμβολοσειρές επιλογών γραμμής εντολών
Το env είναι ένας μηδενικός τερματικός πίνακας δεικτών σε συμβολοσειρές μεταβλητών περιβάλλοντος. Κάθε γραμμή στη μορφή NAME=VALUE
auxv - πίνακας βοηθητικών τιμών (διατίθεται μόνο για PowerPC)
apple - διαδρομή προς το εκτελέσιμο αρχείο (σε MacOS και Darwin)
Βοηθητικό διάνυσμα - ένας πίνακας με διαφορετικά Επιπλέον πληροφορίες, όπως το πραγματικό αναγνωριστικό χρήστη, η σημαία setuid bit, το μέγεθος σελίδας μνήμης και τα παρόμοια.

Το μέγεθος του τμήματος στοίβας μπορεί να προβληθεί στο αρχείο χαρτών:
cat /proc/10918/maps

7ffffffa3000-7ffffffff000 rw-p 00000000 00:00 0

Πριν ο φορτωτής μεταφέρει τον έλεγχο στο main, αρχικοποιεί τα περιεχόμενα των συστοιχιών παραμέτρων γραμμής εντολών, μεταβλητών περιβάλλοντος, βοηθητικού διανύσματος.
Μετά την προετοιμασία, το επάνω μέρος της στοίβας μοιάζει κάπως έτσι για την έκδοση 64 bit.
Διεύθυνση ανώτερης αρχής στην κορυφή.

1. 0x7ffffffff000 Το επάνω σημείο του τμήματος στοίβας. Η κλήση προκαλεί segfault
0x7ffffffff0f8 ΜΗΔΕΝΙΚΟ κενός* 8 0x00"
2. όνομα αρχείου απανθρακώνω 1+ "/tmp/a.out"
απανθρακώνω 1 0x00
...
env απανθρακώνω 1 0x00
...
απανθρακώνω 1 0x00
3. 0x7fffffffe5e0 env απανθρακώνω 1 ..
απανθρακώνω 1 0x00
...
argv απανθρακώνω 1 0x00
...
απανθρακώνω 1 0x00
4. 0x7fffffffe5be argv απανθρακώνω 1+ "/tmp/a.out"
5. Πίνακας τυχαίου μήκους
6. δεδομένα για auxv κενός* 48"
AT_NULL Elf64_auxv_t 16 {0,0}
...
auxv Elf64_auxv_t 16
7. auxv Elf64_auxv_t 16 Π.χ.: (0x0e,0x3e8)
ΜΗΔΕΝΙΚΟ κενός* 8 0x00
...
env απανθρακώνω* 8
8. 0x7fffffffe308 env απανθρακώνω* 8 0x7fffffffe5e0
ΜΗΔΕΝΙΚΟ κενός* 8 0x00
...
argv απανθρακώνω* 8
9. 0x7fffffffe2f8 argv απανθρακώνω* 8 0x7fffffffe5be
10. 0x7fffffffe2f0 argc μακρύς ενθ 8" αριθμός ορισμάτων + 1
11. Τοπικές μεταβλητές και ορίσματα, συναρτήσεις που καλούνται πριν από το main
12. τοπικές μεταβλητές κύρια
13. 0x7fffffffe1fc argc ενθ 4 αριθμός ορισμάτων + 1
0x7fffffffe1f0 argv απανθρακώνω** 8 0x7fffffffe2f8
0x7fffffffe1e8 env απανθρακώνω** 8 0x7fffffffe308
14. Μεταβλητές τοπικές λειτουργίες

«- Δεν βρήκα περιγραφές των πεδίων στα έγγραφα, αλλά είναι καθαρά ορατές στη χωματερή.

Για 32 bit δεν έλεγξα, αλλά πιθανότατα αρκεί απλώς να διαιρέσω τα μεγέθη κατά δύο.

1. Η πρόσβαση σε διευθύνσεις πάνω από το επάνω σημείο προκαλεί Segfault.
2. Μια συμβολοσειρά που περιέχει τη διαδρομή προς το εκτελέσιμο αρχείο.
3. Πίνακας συμβολοσειρών με μεταβλητές περιβάλλοντος
4. Πίνακας συμβολοσειρών με επιλογές γραμμής εντολών
5. Πίνακας τυχαίου μήκους. Η επιλογή του μπορεί να απενεργοποιηθεί με τις εντολές
sysctl -w πυρήνας.randomize_va_space=0
echo 0 > /proc/sys/kernel/randomize_va_space
6. Δεδομένα για το βοηθητικό διάνυσμα (για παράδειγμα, η συμβολοσειρά "x86_64")
7. Βοηθητικό διάνυσμα. Περισσότερες λεπτομέρειες παρακάτω.
8. Μηδενικός τερματικός πίνακας δεικτών σε συμβολοσειρές μεταβλητών περιβάλλοντος
9. Μηδενικός τερματικός πίνακας δεικτών σε συμβολοσειρές παραμέτρων γραμμής εντολών
10. Μια λέξη μηχανής που περιέχει τον αριθμό των παραμέτρων της γραμμής εντολών (ένα από τα ορίσματα των συναρτήσεων "υψηλότερο", βλέπε στοιχείο 11)
11.Τοπικές μεταβλητές και ορίσματα συναρτήσεων που καλούνται πριν από το main(_start,__libc_start_main..)
12. Μεταβλητές που δηλώνονται ως κύρια
13. Ορίσματα κύριας συνάρτησης
14. Μεταβλητές και ορίσματα τοπικών συναρτήσεων.

Βοηθητικό διάνυσμα
Για τα i386 και x86_64, δεν μπορείτε να λάβετε τη διεύθυνση του πρώτου στοιχείου του βοηθητικού διανύσματος, αλλά τα περιεχόμενα αυτού του διανύσματος μπορούν να ληφθούν με άλλους τρόπους. Ένα από αυτά είναι η πρόσβαση στην περιοχή της μνήμης αμέσως μετά τη συστοιχία δεικτών σε συμβολοσειρές μεταβλητών περιβάλλοντος.
Θα πρέπει να μοιάζει κάπως έτσι:
#περιλαμβάνω #περιλαμβάνω int main(int argc, char** argv, char** env)( Elf64_auxv_t *auxv; //x86_64 // Elf32_auxv_t *auxv; //i386 while(*env++ != NULL); //βρείτε την αρχή του βοηθητικού διάνυσμα για ( auxv = (Elf64_auxv_t *)env; auxv->a_type != AT_NULL; auxv++)( printf("addr: %p type: %lx is: 0x%lx\n", auxv, auxv->a_type, auxv ->a_un .a_val); ) printf("\n (void*)(*argv) - (void*)auxv= %p - %p = %ld\n (void*)(argv)-(void*) (&auxv) =%p-%p = %ld\n ", (void*)(*argv), (void*)auxv, (void*)(*argv) - (void*)auxv, (void*) (argv) , (void*)(&auxv), (void*)(argv) - (void*)(&auxv)); printf("\n αντίγραφο argc: %d\n",*((int *)( argv - 1 )); επιστροφή 0;)
Οι δομές Elf(32,64)_auxv_t περιγράφονται στο /usr/include/elf.h. Λειτουργίες για πλήρωση δομών σε linux-kernel/fs/binfmt_elf.c

Ο δεύτερος τρόπος για να λάβετε τα περιεχόμενα του διανύσματος:
hexdump /proc/self/auxv

Η πιο ευανάγνωστη αναπαράσταση λαμβάνεται με τη ρύθμιση μεταβλητή περιβάλλοντος LD_SHOW_AUXV.

LD_SHOW_AUXV=1 ls
AT_HWCAP: bfebfbff // δυνατότητες επεξεργαστή
AT_PAGESZ: 4096 //μέγεθος σελίδας μνήμης
AT_CLKTCK: 100 //χρόνοι συχνότητας ενημέρωσης()
AT_PHDR: 0x400040 //πληροφορίες κεφαλίδας
AT_PHENT: 56
AT_PHNUM: 9
AT_BASE: 0x7fd00b5bc000 //διεύθυνση του διερμηνέα, δηλαδή ld.so
AT_FLAGS: 0x0
AT_ENTRY: 0x402490 //σημείο εισόδου προγράμματος
AT_UID: 1000 // αναγνωριστικά χρήστη και ομάδας
AT_EUID: 1000 //ονομαστικό και αποτελεσματικό
AT_GID: 1000
AT_EGID: 1000
AT_SECURE: 0 //είναι το setuid flag set
AT_RANDOM: 0x7fff30bdc809 //Διεύθυνση 16 τυχαίων byte,
που δημιουργήθηκε κατά την εκκίνηση
AT_SYSINFO_EHDR: 0x7fff30bff000 //δείκτης προς σελίδα που χρησιμοποιείται για
//κλήσεις συστήματος
AT_EXECFN: /bin/ls
AT_PLATFORM: x86_64
Αριστερά είναι το όνομα της μεταβλητής, δεξιά η τιμή. Όλα τα πιθανά ονόματα μεταβλητών και οι περιγραφές τους βρίσκονται στο αρχείο elf.h. (σταθερές με πρόθεμα AT_)

Επιστροφή από το main()
Αφού αρχικοποιηθεί το περιβάλλον διεργασίας, ο έλεγχος μεταφέρεται όχι στη συνάρτηση main(), αλλά στη συνάρτηση _start().
Η main() καλεί ήδη από __libc_start_main. Αυτό τελευταία λειτουργίαέχει ένα ενδιαφέρον χαρακτηριστικό - μεταβιβάζεται ένας δείκτης σε μια συνάρτηση που θα εκτελεστεί μετά την main(). Και αυτός ο δείκτης περνά φυσικά μέσα από τη στοίβα.
Γενικά, τα ορίσματα __libc_start_main έχουν τη μορφή, σύμφωνα με το αρχείο glibc-2.11/sysdeps/ia64/elf/start.S
/*
* Επιχειρήματα για __libc_start_main:
*out0:main
*out1: argc
*out2: argv
* out3: init
* out4: fini // συνάρτηση που καλείται μετά την κύρια
* out5: rtld_fini
*out6: stack_end
*/
Εκείνοι. για να λάβετε τη διεύθυνση του τελικού δείκτη, πρέπει να μετακινήσετε δύο λέξεις μηχανής από την τελευταία τοπική μεταβλητή κύρια.
Να τι συνέβη (η λειτουργικότητα εξαρτάται από την έκδοση του μεταγλωττιστή):
#περιλαμβάνω void **ret; κενό *αποχωρώ; void foo()( void (*boo)(void); //δείκτης συνάρτησης printf("Stack rewrite!\n"); boo = (void (*)(void))leave; boo(); // fini ( ) ) int main(int argc, char *argv, char *envp) ( ανυπόγραφο μακρύ σημάδι int = 0xbfbfbfbfbfbfbfbf; // σημάδι για εργασία από ret = (void**)(&mark+2); // εξαγωγή διεύθυνσης , συνάρτηση καλείται μετά την ολοκλήρωση (fini) leave = *ret; // store *ret = (void*)foo; // overwrite return 0; // call foo() )

Ελπίζω να ήταν ενδιαφέρον.
Καλή τύχη.

Ευχαριστούμε τον χρήστη Xeor για τη χρήσιμη συμβουλή.

Κατά τη δημιουργία μιας εφαρμογής κονσόλας στη γλώσσα προγραμματισμού C++, δημιουργείται αυτόματα μια γραμμή πολύ παρόμοια με αυτήν:

int main(int argc, char* argv) // main() παράμετροι συνάρτησης

Αυτή η γραμμή είναι η κεφαλίδα κύρια λειτουργία main() , οι παράμετροι argс και argv δηλώνονται σε αγκύλες. Έτσι, εάν το πρόγραμμα εκτελείται γραμμή εντολών, τότε είναι δυνατό να περάσετε κάποιες πληροφορίες σε αυτό το πρόγραμμα, για αυτό υπάρχουν οι παράμετροι argc και argv . Η παράμετρος argc είναι τύπου δεδομένων int και περιέχει τον αριθμό των παραμέτρων που μεταβιβάζονται κύρια λειτουργία. Επιπλέον, το argc είναι πάντα τουλάχιστον 1, ακόμη και όταν δεν περνάμε καμία πληροφορία, αφού το όνομα της συνάρτησης θεωρείται η πρώτη παράμετρος. Η παράμετρος argv είναι ένας πίνακας δεικτών σε συμβολοσειρές. Μόνο δεδομένα τύπου συμβολοσειράς μπορούν να περάσουν από τη γραμμή εντολών. Οι δείκτες και οι συμβολοσειρές είναι δύο μεγάλα θέματα για τα οποία έχουν δημιουργηθεί ξεχωριστές ενότητες. Έτσι, μέσω της παραμέτρου argv μεταδίδεται οποιαδήποτε πληροφορία. Ας αναπτύξουμε ένα πρόγραμμα που θα τρέξουμε μέσα από τη γραμμή εντολών. Γραμμή Windows, και του διαβιβάστε κάποιες πληροφορίες.

// argc_argv.cpp: Καθορίζει το σημείο εισόδου για την εφαρμογή της κονσόλας. #include "stdafx.h" #include χρησιμοποιώντας namespace std? int main(int argc, char* argv) (αν (argc ><< argv<

// code Code::Blocks

// Κώδικας Dev-C++

// argc_argv.cpp: Καθορίζει το σημείο εισόδου για την εφαρμογή της κονσόλας. #περιλαμβάνω χρησιμοποιώντας namespace std? int main(int argc, char* argv) ( if (argc > 1)// αν περάσουμε ορίσματα, τότε το argc θα είναι μεγαλύτερο από 1 (ανάλογα με τον αριθμό των ορισμών) ( cout<< argv<

Μετά την αποσφαλμάτωση του προγράμματος, ανοίξτε τη γραμμή εντολών των Windows και σύρετε το εκτελέσιμο αρχείο του προγράμματός μας στο παράθυρο της γραμμής εντολών, η πλήρης διαδρομή προς το πρόγραμμα θα εμφανιστεί στη γραμμή εντολών (αλλά μπορείτε να γράψετε τη διαδρομή προς το πρόγραμμα χειροκίνητα), μετά που μπορείτε να πατήσετε ΕΙΣΑΓΩκαι το πρόγραμμα θα ξεκινήσει (βλ. Εικόνα 1).

Εικόνα 1 - Παράμετροι της κύριας συνάρτησης

Δεδομένου ότι μόλις εκτελέσαμε το πρόγραμμα και δεν του περάσαμε κανένα όρισμα, εμφανίστηκε το μήνυμα Όχι ορίσματα. Το σχήμα 2 δείχνει την εκκίνηση του ίδιου προγράμματος μέσω της γραμμής εντολών, αλλά με το όρισμα Open που έχει μεταβιβαστεί σε αυτό.

Εικόνα 2 - Παράμετροι της κύριας συνάρτησης

Το επιχείρημα είναι η λέξη Open , όπως μπορείτε να δείτε από το σχήμα, αυτή η λέξη εμφανίστηκε στην οθόνη. Μπορείτε να περάσετε πολλές παραμέτρους ταυτόχρονα, χωρίζοντάς τις με κόμμα. Εάν είναι απαραίτητο να περάσετε μια παράμετρο που αποτελείται από πολλές λέξεις, τότε αυτές πρέπει να περικλείονται σε διπλά εισαγωγικά και στη συνέχεια αυτές οι λέξεις θα θεωρηθούν ως μία παράμετρος. Για παράδειγμα, το σχήμα δείχνει την έναρξη του προγράμματος, μεταβιβάζοντάς του ένα όρισμα που αποτελείται από δύο λέξεις - Λειτουργεί .

Εικόνα 3 - Παράμετροι της κύριας συνάρτησης

Και αν αφαιρέσετε τα εισαγωγικά. Τότε θα δούμε μόνο τη λέξη It. Εάν δεν σκοπεύετε να μεταβιβάσετε καμία πληροφορία κατά την εκκίνηση του προγράμματος, τότε μπορείτε να αφαιρέσετε τα ορίσματα στη συνάρτηση main(), μπορείτε επίσης να αλλάξετε τα ονόματα αυτών των ορισμάτων. Μερικές φορές υπάρχουν τροποποιήσεις των παραμέτρων argc και argv, αλλά όλα εξαρτώνται από τον τύπο της εφαρμογής που δημιουργείται ή από το περιβάλλον ανάπτυξης.

Προαιρετικά και ονομασμένα ορίσματα

Προαιρετικά επιχειρήματα

Η C# 4.0 εισάγει μια νέα δυνατότητα που βελτιώνει την ευκολία του καθορισμού ορισμάτων κατά την κλήση μιας μεθόδου. Αυτό το εργαλείο ονομάζεται προαιρετικά επιχειρήματακαι σας επιτρέπει να ορίσετε μια προεπιλεγμένη τιμή για μια παράμετρο μεθόδου. Αυτή η τιμή θα χρησιμοποιηθεί από προεπιλογή εάν δεν έχει καθοριστεί αντίστοιχο όρισμα για την παράμετρο κατά την κλήση της μεθόδου. Επομένως, δεν είναι απαραίτητο να προσδιορίσετε ένα όρισμα για μια τέτοια παράμετρο. Τα προαιρετικά ορίσματα διευκολύνουν την κλήση μεθόδων, όπου τα προεπιλεγμένα ορίσματα εφαρμόζονται σε ορισμένες παραμέτρους. Μπορούν επίσης να χρησιμοποιηθούν ως «σύντομη» μορφή υπερφόρτωσης μεθόδου.

Η κύρια ώθηση για την προσθήκη προαιρετικών ορισμάτων ήταν η ανάγκη απλοποίησης της αλληλεπίδρασης με αντικείμενα COM. Σε πολλά μοντέλα αντικειμένων της Microsoft (για παράδειγμα, Microsoft Office), η λειτουργικότητα παρέχεται μέσω αντικειμένων COM, πολλά από τα οποία γράφτηκαν πριν από πολύ καιρό και σχεδιάστηκαν για να χρησιμοποιούν προαιρετικές παραμέτρους.

Ένα παράδειγμα χρήσης προαιρετικών ορισμάτων φαίνεται παρακάτω:

Χρήση του συστήματος. χρησιμοποιώντας System.Collections.Generic; χρησιμοποιώντας System.Linq; χρησιμοποιώντας System.Text; namespace ConsoleApplication1 ( class Program ( // Τα ορίσματα b και c είναι προαιρετικά όταν καλείτε static int mySum(int a, int b = 5, int c = 10) ( return a + b + c; ) static void Main() ( int sum1 = mySum(3); int sum2 = mySum(3,12); Console.WriteLine("Sum1 = "+sum1); Console.WriteLine("Sum2 = "+sum2); Console.ReadLine(); ) ) )

Θα πρέπει να ληφθεί υπόψη ότι όλα τα προαιρετικά ορίσματα πρέπει απαραίτητα να υποδεικνύονται στα δεξιά των απαιτούμενων. Εκτός από τις μεθόδους, προαιρετικά ορίσματα μπορούν να χρησιμοποιηθούν σε κατασκευαστές, ευρετήρια και εκπροσώπους.

Ένα πλεονέκτημα των προαιρετικών ορισμάτων είναι ότι διευκολύνουν τον προγραμματιστή να αντιμετωπίσει σύνθετες κλήσεις μεθόδων και κατασκευαστή. Άλλωστε, συχνά είναι απαραίτητο να ορίσετε περισσότερες παραμέτρους σε μια μέθοδο από ό,τι συνήθως απαιτείται. Και σε περιπτώσεις όπως αυτή, ορισμένες από αυτές τις παραμέτρους μπορούν να γίνουν προαιρετικές με προσεκτική χρήση των προαιρετικών ορισμάτων. Αυτό σημαίνει ότι πρέπει να περάσουν μόνο εκείνα τα επιχειρήματα που είναι σημαντικά στη συγκεκριμένη περίπτωση και όχι όλα τα επιχειρήματα που διαφορετικά θα έπρεπε να απαιτούνται. Αυτή η προσέγγιση μας επιτρέπει να εκλογικεύσουμε τη μέθοδο και να απλοποιήσουμε τον χειρισμό της από τον προγραμματιστή.

Επώνυμα Επιχειρήματα

Ένα άλλο χαρακτηριστικό που προστέθηκε στο C# με την κυκλοφορία του .NET 4.0 είναι η υποστήριξη για τα λεγόμενα επώνυμα επιχειρήματα. Όπως γνωρίζετε, όταν μεταβιβάζετε ορίσματα σε μια μέθοδο, η σειρά με την οποία εμφανίζονται, κατά κανόνα, πρέπει να ταιριάζει με τη σειρά με την οποία ορίζονται οι παράμετροι στην ίδια τη μέθοδο. Με άλλα λόγια, η τιμή ορίσματος εκχωρείται στην παράμετρο από τη θέση της στη λίστα ορισμάτων.

Τα επώνυμα ορίσματα έχουν σχεδιαστεί για να ξεπεραστεί αυτός ο περιορισμός. Ένα όρισμα με όνομα σάς επιτρέπει να καθορίσετε το όνομα της παραμέτρου στην οποία έχει εκχωρηθεί η τιμή της. Και σε αυτή την περίπτωση, η σειρά των επιχειρημάτων δεν έχει πλέον σημασία. Έτσι, τα ονομασμένα ορίσματα είναι κάπως παρόμοια με τους αρχικοποιητές αντικειμένων που αναφέρθηκαν προηγουμένως, αν και διαφέρουν από αυτά ως προς τη σύνταξή τους. Για να καθορίσετε ένα όρισμα με όνομα, χρησιμοποιήστε την ακόλουθη μορφή σύνταξης:

parameter_name: τιμή

Εδώ όνομα_παραμέτρουυποδηλώνει το όνομα της παραμέτρου στην οποία μεταβιβάζεται η τιμή. Φυσικά, το parameter_name πρέπει να είναι το όνομα μιας έγκυρης παραμέτρου για τη μέθοδο που καλείται.

Μπορείτε να μεταβιβάσετε ορισμένα ορίσματα σε προγράμματα C. Όταν καλείται main() στην αρχή του υπολογισμού, μεταβιβάζονται σε αυτήν τρεις παράμετροι. Το πρώτο από αυτά καθορίζει τον αριθμό των ορισμάτων εντολής κατά την πρόσβαση στο πρόγραμμα. Το δεύτερο είναι ένας πίνακας δεικτών σε συμβολοσειρές χαρακτήρων που περιέχουν αυτά τα ορίσματα (ένα όρισμα ανά συμβολοσειρά). Το τρίτο είναι επίσης μια συστοιχία δεικτών σε συμβολοσειρές χαρακτήρων, χρησιμοποιείται για πρόσβαση στις παραμέτρους του λειτουργικού συστήματος (μεταβλητές περιβάλλοντος).

Οποιαδήποτε τέτοια γραμμή αντιπροσωπεύεται ως:

μεταβλητή = τιμή\0

Η τελευταία γραμμή μπορεί να βρεθεί από δύο μηδενικά.

Ας ονομάσουμε τα ορίσματα της συνάρτησης main() αντίστοιχα: argc, argv και env (οποιαδήποτε άλλα ονόματα είναι πιθανά). Στη συνέχεια επιτρέπονται οι ακόλουθες περιγραφές:

κύρια (int argc, char *argv)

κύρια (int argc, char *argv, char *env)

Ας υποθέσουμε ότι υπάρχει κάποιο πρόγραμμα prog.exe στη μονάδα δίσκου A:. Ας το αντιμετωπίσουμε ως εξής:

A:\>αρχείο prog.exe1 αρχείο2 αρχείο3

Στη συνέχεια, το argv είναι ένας δείκτης στη συμβολοσειρά A:\prog.exe, ο argv είναι ένας δείκτης στο αρχείο συμβολοσειράς1 και ούτω καθεξής. Το πρώτο πραγματικό επιχείρημα επισημαίνεται από το argv και το τελευταίο από το argv. Εάν argc=1, τότε δεν υπάρχουν παράμετροι μετά το όνομα του προγράμματος στη γραμμή εντολών. Στο παράδειγμά μας, argc=4.

αναδρομή

Η αναδρομή είναι μια μέθοδος κλήσης στην οποία μια συνάρτηση καλεί τον εαυτό της.

Σημαντικό σημείο στη σύνταξη ενός αναδρομικού προγράμματος είναι η οργάνωση της εξόδου. Είναι εύκολο να κάνουμε το λάθος εδώ ότι η συνάρτηση θα καλείται συνεχώς επ' αόριστον. Επομένως, η αναδρομική διαδικασία πρέπει, βήμα προς βήμα, να απλοποιήσει το πρόβλημα έτσι ώστε στο τέλος να εμφανιστεί μια μη αναδρομική λύση για αυτό. Η χρήση αναδρομής δεν είναι πάντα επιθυμητή, καθώς μπορεί να οδηγήσει σε υπερχείλιση στοίβας.

Λειτουργίες βιβλιοθήκης

Στα συστήματα προγραμματισμού, οι υπορουτίνες για την επίλυση κοινών προβλημάτων συνδυάζονται σε βιβλιοθήκες. Αυτές οι εργασίες περιλαμβάνουν: υπολογισμό μαθηματικών συναρτήσεων, εισαγωγή/εξαγωγή δεδομένων, επεξεργασία συμβολοσειρών, αλληλεπίδραση με εργαλεία λειτουργικού συστήματος κ.λπ. Η χρήση υπορουτίνων βιβλιοθήκης απαλλάσσει τον χρήστη από την ανάγκη ανάπτυξης κατάλληλων εργαλείων και του παρέχει μια πρόσθετη υπηρεσία. Οι λειτουργίες που περιλαμβάνονται στις βιβλιοθήκες παρέχονται με το σύστημα προγραμματισμού. Οι δηλώσεις τους δίνονται σε αρχεία *.h (αυτά είναι τα λεγόμενα αρχεία include ή header). Επομένως, όπως αναφέρθηκε παραπάνω, στην αρχή του προγράμματος με τις λειτουργίες βιβλιοθήκης, θα πρέπει να υπάρχουν γραμμές όπως:

#περιλαμβάνω<включаемый_файл_типа_h>

Για παράδειγμα:

#περιλαμβάνω

Υπάρχουν επίσης δυνατότητες επέκτασης και δημιουργίας νέων βιβλιοθηκών με προγράμματα χρηστών.

Στις καθολικές μεταβλητές εκχωρείται μια σταθερή θέση στη μνήμη για τη διάρκεια του προγράμματος. Οι τοπικές μεταβλητές αποθηκεύονται στη στοίβα. Ανάμεσά τους υπάρχει μια περιοχή μνήμης για δυναμική κατανομή.

Οι συναρτήσεις malloc() και free() χρησιμοποιούνται για τη δυναμική κατανομή της ελεύθερης μνήμης. Η συνάρτηση malloc() εκχωρεί μνήμη, η συνάρτηση free() την ελευθερώνει. Τα πρωτότυπα αυτών των συναρτήσεων αποθηκεύονται στο αρχείο κεφαλίδας stdlib.h και μοιάζουν με αυτό:

void *malloc(size_t size);

void *free(void *p);

Η συνάρτηση malloc() επιστρέφει έναν δείκτη τύπου void. για σωστή χρήση, η τιμή της συνάρτησης πρέπει να μετατραπεί σε δείκτη στον κατάλληλο τύπο. Με επιτυχία, η συνάρτηση επιστρέφει έναν δείκτη στο πρώτο byte ελεύθερης μνήμης μεγέθους. Εάν δεν υπάρχει αρκετή μνήμη, επιστρέφεται η τιμή 0. Η λειτουργία sizeof() χρησιμοποιείται για τον προσδιορισμό του αριθμού των byte που απαιτούνται για μια μεταβλητή.

Ένα παράδειγμα χρήσης αυτών των συναρτήσεων:

#περιλαμβάνω

#περιλαμβάνω

p = (int *) malloc(100 * sizeof(int)); /* Εκχώρηση μνήμης για 100

ακέραιοι */

printf("Εκτός μνήμης\n");

για (i = 0; i< 100; ++i) *(p+i) = i; /* Использование памяти */

για (i = 0; i< 100; ++i) printf("%d", *(p++));

δωρεάν (p); /* Ελεύθερη μνήμη */

Πριν χρησιμοποιήσετε τον δείκτη που επιστράφηκε από το malloc(), πρέπει να βεβαιωθείτε ότι υπάρχει αρκετή μνήμη (ο δείκτης δεν είναι μηδενικός).

Προεπεξεργαστής

Ένας προεπεξεργαστής C είναι ένα πρόγραμμα που επεξεργάζεται την είσοδο σε έναν μεταγλωττιστή. Ο προεπεξεργαστής εξετάζει το πρόγραμμα πηγής και εκτελεί τις ακόλουθες ενέργειες: συνδέει τα δεδομένα αρχεία σε αυτό, εκτελεί αντικαταστάσεις και επίσης διαχειρίζεται τις συνθήκες μεταγλώττισης. Ο προεπεξεργαστής προορίζεται για γραμμές προγράμματος που ξεκινούν με το σύμβολο #. Μόνο μία εντολή (οδηγία προεπεξεργαστή) επιτρέπεται ανά γραμμή.

Διευθυντικός

#define αντικατάσταση αναγνωριστικού

προκαλεί το ακόλουθο κείμενο προγράμματος να αντικαταστήσει το αναγνωριστικό με το όνομα με το κείμενο αντικατάστασης (σημειώστε την έλλειψη ερωτηματικού στο τέλος αυτής της εντολής). Ουσιαστικά, αυτή η οδηγία εισάγει έναν ορισμό μακροεντολής (macro), όπου "αναγνωριστικό" είναι το όνομα του ορισμού μακροεντολής και "υποκατάσταση" είναι η ακολουθία χαρακτήρων με τους οποίους ο προεπεξεργαστής αντικαθιστά το καθορισμένο όνομα όταν το βρίσκει στο κείμενο του προγράμματος. Το όνομα μιας μακροεντολής γράφεται συνήθως με κεφαλαία.

Εξετάστε παραδείγματα:

Η πρώτη γραμμή αναγκάζει το πρόγραμμα να αντικαταστήσει το αναγνωριστικό MAX με τη σταθερά 25. Η δεύτερη σάς επιτρέπει να χρησιμοποιείτε στο κείμενο αντί για το αρχικό σγουρό άγκιστρο (() τη λέξη BEGIN.

Σημειώστε ότι επειδή ο προεπεξεργαστής δεν ελέγχει τη συμβατότητα μεταξύ των συμβολικών ονομάτων των ορισμών μακροεντολών και του περιβάλλοντος στο οποίο χρησιμοποιούνται, συνιστάται να ορίσετε τέτοια αναγνωριστικά όχι με την οδηγία #define, αλλά με τη λέξη-κλειδί const με ρητή ένδειξη τύπου (αυτό ισχύει περισσότερο για το C + +):

const int MAX = 25;

(ο τύπος int μπορεί να παραλειφθεί, όπως έχει οριστεί από προεπιλογή).

Εάν η οδηγία #define μοιάζει με:

#define identifier(identifier, ..., identifier) ​​αντικατάσταση

και δεν υπάρχει κενό μεταξύ του πρώτου αναγνωριστικού και της αρχικής παρένθεσης, τότε αυτός είναι ένας ορισμός αντικατάστασης μακροεντολής με ορίσματα. Για παράδειγμα, μετά την εμφάνιση μιας γραμμής όπως:

#define READ(val) scanf("%d", &val)

δήλωση READ(y); αντιμετωπίζεται το ίδιο με το scanf("%d",&y);. Εδώ το val είναι ένα όρισμα και η μακροεντολή πραγματοποιείται με το όρισμα.

Εάν υπάρχουν μεγάλοι ορισμοί στην αντικατάσταση που συνεχίζονται στην επόμενη γραμμή, ένας χαρακτήρας \ τοποθετείται στο τέλος της επόμενης συνεχόμενης γραμμής.

Μπορείτε να τοποθετήσετε αντικείμενα διαχωρισμένα με ## χαρακτήρες σε έναν ορισμό μακροεντολής, για παράδειγμα:

#define PR(x, y) x##y

Μετά από αυτό, ο PR(a, 3) θα καλέσει την αντικατάσταση a3. Ή, για παράδειγμα, ένας μακροορισμός

#define z(a, b, c, d) a(b##c##d)

θα αλλάξει το z(sin, x, +, y) σε sin(x+y).

Ο χαρακτήρας # που τοποθετείται πριν από ένα όρισμα μακροεντολής υποδεικνύει ότι έχει μετατραπεί σε συμβολοσειρά. Για παράδειγμα, μετά την οδηγία

#define PRIM(var) printf(#var"= %d", var)

το ακόλουθο τμήμα του κειμένου του προγράμματος

μετατρέπεται ως εξής:

printf("year""= %d", έτος);

Ας περιγράψουμε άλλες οδηγίες προεπεξεργαστή. Η οδηγία #include έχει προηγηθεί. Μπορεί να χρησιμοποιηθεί σε δύο μορφές:

#include "όνομα αρχείου"

#περιλαμβάνω<имя файла>

Το αποτέλεσμα και των δύο εντολών είναι η συμπερίληψη αρχείων με το καθορισμένο όνομα στο πρόγραμμα. Το πρώτο φορτώνει ένα αρχείο από τον τρέχοντα κατάλογο ή τον κατάλογο που έχει καθοριστεί ως πρόθεμα. Η δεύτερη εντολή αναζητά το αρχείο σε τυπικές θέσεις που ορίζονται στο σύστημα προγραμματισμού. Εάν το αρχείο του οποίου το όνομα είναι γραμμένο σε διπλά εισαγωγικά δεν βρεθεί στον καθορισμένο κατάλογο, τότε η αναζήτηση θα συνεχιστεί στους υποκαταλόγους που έχουν καθοριστεί για την εντολή #include<...>. Οι οδηγίες #include μπορούν να είναι ένθετες μεταξύ τους.

Η επόμενη ομάδα οδηγιών σάς επιτρέπει να συγκεντρώνετε επιλεκτικά μέρη του προγράμματος. Αυτή η διαδικασία ονομάζεται μεταγλώττιση υπό όρους. Αυτή η ομάδα περιλαμβάνει τις οδηγίες #if, #else, #elif, #endif, #ifdef, #ifndef. Η βασική μορφή της οδηγίας #if είναι:

#αν σταθερή_έκφραση statement_sequence

Εδώ ελέγχεται η τιμή της σταθερής έκφρασης. Εάν είναι αληθές, τότε εκτελείται η δεδομένη ακολουθία εντολών και εάν είναι ψευδής, τότε αυτή η ακολουθία εντολών παραλείπεται.

Η ενέργεια της οδηγίας #else είναι παρόμοια με την ενέργεια της εντολής else στη γλώσσα C, για παράδειγμα:

#αν σταθερή_έκφραση

δήλωση_ακολουθία_2

Εδώ, αν η σταθερά έκφραση είναι αληθής, τότε εκτελείται η ακολουθία_των_τελεστών_1 και εάν είναι ψευδής, η ακολουθία_των_τελεστών_2.

Η οδηγία #elif σημαίνει μια ενέργεια τύπου "άλλο εάν". Η κύρια μορφή χρήσης του είναι η εξής:

#αν σταθερή_έκφραση

δήλωση_ακολουθία

#elif σταθερά_έκφραση_1

δήλωση_ακολουθία_1

#elif σταθερά_έκφραση_n

ακολουθία_δηλώσεων_n

Αυτή η φόρμα είναι παρόμοια με το κατασκεύασμα της γλώσσας C της φόρμας: αν...άλλο αν...άλλο αν...

Διευθυντικός

Αναγνωριστικό #ifdef

ορίζει εάν το καθορισμένο αναγνωριστικό έχει οριστεί επί του παρόντος, π.χ. αν περιλαμβανόταν σε οδηγίες της μορφής #define. Προβολή γραμμής

Αναγνωριστικό #ifndef

ελέγχει εάν το καθορισμένο αναγνωριστικό δεν έχει καθοριστεί αυτήν τη στιγμή. Οποιαδήποτε από αυτές τις οδηγίες μπορεί να ακολουθηθεί από έναν αυθαίρετο αριθμό γραμμών κειμένου, που ενδεχομένως περιέχουν μια δήλωση #else (δεν μπορεί να χρησιμοποιηθεί το #elif) και τελειώνει με τη γραμμή #endif. Εάν η συνθήκη που ελέγχεται είναι αληθής, τότε όλες οι γραμμές μεταξύ #else και #endif αγνοούνται και εάν είναι false, τότε οι γραμμές μεταξύ του check και #else (αν δεν υπάρχει λέξη #else, τότε #endif). Οι οδηγίες #if και #ifndef μπορούν να τοποθετηθούν η μία μέσα στην άλλη.

Δείτε την οδηγία

Αναγνωριστικό #undef

κάνει το καθορισμένο αναγνωριστικό να θεωρείται απροσδιόριστο, π.χ. δεν αντικαθίσταται.

Εξετάστε παραδείγματα. Οι τρεις οδηγίες είναι:

ελέγξτε αν έχει οριστεί το αναγνωριστικό WRITE (δηλαδή ήταν μια εντολή της μορφής #define WRITE...), και αν ναι, τότε το όνομα WRITE θεωρείται απροσδιόριστο, δηλ. δεν αντικαθίσταται.

οδηγίες

#define WRITE fprintf

ελέγξτε αν το αναγνωριστικό WRITE δεν έχει οριστεί και αν ναι, τότε προσδιορίζεται το αναγνωριστικό WRITE αντί για το όνομα fprintf.

Η οδηγία #error είναι γραμμένη με την ακόλουθη μορφή:

#error error_message

Εάν εμφανίζεται στο κείμενο του προγράμματος, τότε η μεταγλώττιση σταματά και εμφανίζεται ένα μήνυμα σφάλματος στην οθόνη εμφάνισης. Αυτή η εντολή χρησιμοποιείται κυρίως κατά τη φάση εντοπισμού σφαλμάτων. Σημειώστε ότι το μήνυμα σφάλματος δεν χρειάζεται να περικλείεται σε διπλά εισαγωγικά.

Η οδηγία #line προορίζεται να αλλάξει τις τιμές των μεταβλητών _LINE_ και _FILE_ που ορίζονται στο σύστημα προγραμματισμού C. Η μεταβλητή _LINE_ περιέχει τον αριθμό γραμμής του προγράμματος που εκτελείται αυτήν τη στιγμή. Το αναγνωριστικό _FILE_ είναι ένας δείκτης σε μια συμβολοσειρά με το όνομα του προγράμματος που μεταγλωττίζεται. Η οδηγία #line είναι γραμμένη ως εξής:

#line αριθμός "όνομα αρχείου"

Εδώ ο αριθμός είναι οποιοσδήποτε θετικός ακέραιος που θα εκχωρηθεί στη μεταβλητή _LINE_, το όνομα αρχείου είναι μια προαιρετική παράμετρος που παρακάμπτει την τιμή του _FILE_.

Η οδηγία #pragma σάς επιτρέπει να μεταβιβάσετε ορισμένες οδηγίες στον μεταγλωττιστή. Για παράδειγμα, η γραμμή

υποδεικνύει ότι υπάρχουν συμβολοσειρές γλώσσας συναρμολόγησης σε ένα πρόγραμμα C. Για παράδειγμα:

Εξετάστε ορισμένα καθολικά αναγνωριστικά ή ονόματα μακροεντολών (ονόματα ορισμών μακροεντολών). Ορίζονται πέντε τέτοια ονόματα: _LINE_, _FILE_, _DATE_, _TIME_, _STDC_. Δύο από αυτά (_LINE_ και _FILE_) έχουν ήδη περιγραφεί παραπάνω. Το αναγνωριστικό _DATE_ καθορίζει μια συμβολοσειρά που αποθηκεύει την ημερομηνία μετάφρασης του αρχείου προέλευσης σε κώδικα αντικειμένου. Το αναγνωριστικό _TIME_ καθορίζει μια συμβολοσειρά που αποθηκεύει το χρόνο που το αρχείο προέλευσης μεταφράστηκε σε κώδικα αντικειμένου. Η μακροεντολή _STDC_ έχει τιμή 1 εάν χρησιμοποιούνται τυπικά καθορισμένα ονόματα μακροεντολών. Διαφορετικά, αυτή η μεταβλητή δεν θα οριστεί.


Μερικές φορές κατά την εκκίνηση ενός προγράμματος είναι χρήσιμο να του δίνετε κάποιες πληροφορίες. Συνήθως, αυτές οι πληροφορίες μεταβιβάζονται στη συνάρτηση main() μέσω ορισμάτων γραμμής εντολών. Επιχείρημα γραμμής εντολώνείναι πληροφορίες που εισάγονται στη γραμμή εντολών του λειτουργικού συστήματος μετά το όνομα του προγράμματος. Για παράδειγμα, για να ξεκινήσετε τη μεταγλώττιση ενός προγράμματος, πρέπει να πληκτρολογήσετε τα ακόλουθα στη γραμμή εντολών μετά την προτροπή:

cc όνομα_προγράμματος

όνομα_προγράμματοςείναι ένα όρισμα γραμμής εντολών που καθορίζει το όνομα του προγράμματος που πρόκειται να μεταγλωττίσετε.

Για την αποδοχή ορισμάτων γραμμής εντολών, χρησιμοποιούνται δύο ειδικά ενσωματωμένα ορίσματα: argc και argv . Η παράμετρος argc περιέχει τον αριθμό των ορισμάτων στη γραμμή εντολών και είναι ένας ακέραιος αριθμός και είναι πάντα τουλάχιστον 1 επειδή το πρώτο όρισμα είναι το όνομα του προγράμματος. Και η παράμετρος argv είναι ένας δείκτης σε μια σειρά δεικτών σε συμβολοσειρές. Σε αυτόν τον πίνακα, κάθε στοιχείο δείχνει σε κάποιο όρισμα γραμμής εντολών. Όλα τα ορίσματα της γραμμής εντολών είναι συμβολοσειρές, επομένως η μετατροπή οποιωνδήποτε αριθμών στην επιθυμητή δυαδική μορφή πρέπει να παρέχεται στο πρόγραμμα όταν αυτό αναπτύσσεται.

Ακολουθεί ένα απλό παράδειγμα χρήσης του ορίσματος της γραμμής εντολών. Στην οθόνη εμφανίζεται η λέξη Hello και το όνομά σας, τα οποία πρέπει να καθοριστούν ως όρισμα γραμμής εντολών.

#περιλαμβάνω #περιλαμβάνω int main(int argc, char *argv) ( if(argc!=2) ( printf("Ξεχάσατε να εισαγάγετε το όνομά σας.\n"); exit(1); ) printf("Γεια %s", argv) ; επιστροφή 0;)

Εάν ονομάσατε αυτό το πρόγραμμα (όνομα) και το όνομά σας είναι Tom, τότε για να εκτελέσετε το πρόγραμμα, εισαγάγετε το όνομα Tom στη γραμμή εντολών. Ως αποτέλεσμα της εκτέλεσης του προγράμματος, το μήνυμα Hello, Tom θα εμφανιστεί στην οθόνη.

Σε πολλά περιβάλλοντα, όλα τα ορίσματα της γραμμής εντολών πρέπει να διαχωρίζονται μεταξύ τους με ένα διάστημα ή μια καρτέλα. Τα κόμματα, τα ερωτηματικά και οι παρόμοιοι χαρακτήρες δεν θεωρούνται διαχωριστικά. Για παράδειγμα,

Run Spot, τρέξε

αποτελείται από τρεις συμβολοσειρές χαρακτήρων, ενώ

Έρικ, Ρικ, Φρεντ

είναι μια συμβολοσειρά ενός χαρακτήρα - τα κόμματα γενικά δεν θεωρούνται οριοθέτες.

Εάν η συμβολοσειρά περιέχει κενά, τότε σε ορισμένα περιβάλλοντα η συμβολοσειρά μπορεί να περικλείεται σε διπλά εισαγωγικά για να αποτραπεί η δημιουργία πολλαπλών ορισμάτων. Ως αποτέλεσμα, ολόκληρη η συμβολοσειρά θα θεωρηθεί ως ένα όρισμα. Για να μάθετε περισσότερα σχετικά με τον τρόπο ρύθμισης των επιλογών γραμμής εντολών στο λειτουργικό σας σύστημα, ανατρέξτε στην τεκμηρίωση για αυτό το σύστημα.

Είναι πολύ σημαντικό να δηλώσετε σωστά το argv. Δείτε πώς το κάνουν πιο συχνά:

Char *argv;

Οι κενές αγκύλες υποδεικνύουν ότι ο πίνακας έχει αόριστο μήκος. Τώρα μπορείτε να αποκτήσετε πρόσβαση σε μεμονωμένα ορίσματα με ευρετηρίαση του πίνακα argv. Για παράδειγμα, το argv δείχνει την πρώτη συμβολοσειρά χαρακτήρων, η οποία είναι πάντα το όνομα του προγράμματος. Το argv δείχνει το πρώτο επιχείρημα και ούτω καθεξής.

Ένα άλλο μικρό παράδειγμα χρήσης ορισμάτων γραμμής εντολών είναι το πρόγραμμα αντίστροφης μέτρησης παρακάτω. Αυτό το πρόγραμμα μετρά αντίστροφα από κάποια τιμή (που καθορίζεται στη γραμμή εντολών) και εκπέμπει έναν ήχο όταν φτάσει στο 0. Σημειώστε ότι το πρώτο όρισμα που περιέχει την αρχική τιμή μετατρέπεται σε ακέραια τιμή χρησιμοποιώντας την τυπική συνάρτηση atoi () . Εάν το δεύτερο όρισμα της γραμμής εντολών (και αν πάρουμε το όνομα του προγράμματος ως τρίτο όρισμα) είναι η συμβολοσειρά "display" (έξοδος στην οθόνη), τότε θα εμφανιστεί το αποτέλεσμα της αντίστροφης μέτρησης (με αντίστροφη σειρά). στην οθόνη.

/* Πρόγραμμα για αντίστροφη μέτρηση. */ #περιλαμβάνω #περιλαμβάνω #περιλαμβάνω #περιλαμβάνω int main(int argc, char *argv) ( int disp, count; if(argc<2) { printf("В командной строке необходимо ввести число, с которого\n"); printf("начинается отсчет. Попробуйте снова.\n"); exit(1); } if(argc==3 && !strcmp(argv, "display")) disp = 1; else disp = 0; for(count=atoi(argv); count; --count) if(disp) printf("%d\n", count); putchar("\a"); /* здесь подается звуковой сигнал */ printf("Счет закончен"); return 0; }

Σημειώστε ότι εάν δεν καθορίζονται ορίσματα γραμμής εντολών, θα εμφανιστεί ένα μήνυμα σφάλματος. Τα προγράμματα με ορίσματα γραμμής εντολών κάνουν συχνά τα εξής: όταν ο χρήστης εκτελεί αυτά τα προγράμματα χωρίς να εισάγει τις απαιτούμενες πληροφορίες, εμφανίζονται οδηγίες σχετικά με τον σωστό καθορισμό των ορισμάτων.

Για να αποκτήσετε πρόσβαση σε έναν χαρακτήρα σε ένα από τα ορίσματα της γραμμής εντολών, εισαγάγετε το δεύτερο ευρετήριο στο argv. Για παράδειγμα, το παρακάτω πρόγραμμα εκτυπώνει χαρακτήρα προς χαρακτήρα όλα τα ορίσματα με τα οποία κλήθηκε:

#περιλαμβάνω int main(int argc, char *argv) ( int t, i; for(t=0; t

Θυμηθείτε, το πρώτο ευρετήριο του argv παρέχει πρόσβαση στη συμβολοσειρά και το δεύτερο ευρετήριο παρέχει πρόσβαση στους μεμονωμένους χαρακτήρες του.

Συνήθως το argc και το argv χρησιμοποιούνται για να περάσουν τις αρχικές εντολές στο πρόγραμμα που θα χρειαστεί κατά την εκκίνηση. Για παράδειγμα, τα ορίσματα γραμμής εντολών συχνά καθορίζουν πληροφορίες όπως ένα όνομα αρχείου, μια επιλογή ή μια εναλλακτική συμπεριφορά. Η χρήση ορισμάτων γραμμής εντολών δίνει στο πρόγραμμά σας μια "επαγγελματική εμφάνιση" και διευκολύνει τη χρήση του σε αρχεία δέσμης.

Τα ονόματα argc και argv είναι παραδοσιακά αλλά δεν απαιτούνται. Μπορείτε να ονομάσετε αυτές τις δύο παραμέτρους στη συνάρτηση main() όπως θέλετε. Επίσης, ορισμένοι μεταγλωττιστές ενδέχεται να υποστηρίζουν -πρόσθετα ορίσματα για το main(), οπότε φροντίστε να ελέγξετε την τεκμηρίωση για τον μεταγλωττιστή σας.

Όταν ένα πρόγραμμα δεν απαιτεί παραμέτρους γραμμής εντολών, είναι πιο συνηθισμένο να δηλώνεται ρητά η συνάρτηση main() ότι δεν έχει παραμέτρους. Σε αυτήν την περίπτωση, η λέξη-κλειδί void χρησιμοποιείται στη λίστα παραμέτρων αυτής της συνάρτησης.