C (γλώσσα προγραμματισμού)

Η C (προφέρεται "σι") είναι μια διαδικαστική γλώσσα προγραμματισμού γενικής χρήσης, η οποία αναπτύχθηκε αρχικά, μεταξύ του 1969 και του 1973, από τον Ντένις Ρίτσι στα εργαστήρια AT&T Bell Labs για να χρησιμοποιηθεί για την ανάπτυξη του λειτουργικού συστήματος UNIX. Όπως οι περισσότερες διαδικαστικές γλώσσες προγραμματισμού που ακολουθούν την παράδοση της ALGOL, η C έχει δυνατότητες δομημένου προγραμματισμού και επιτρέπει τη χρήση αναδρομής (αλλά όχι και εμφωλευμένων συναρτήσεων), ενώ, ο στατικός ορισμός του τύπου των μεταβλητών που επιβάλλει, προλαμβάνει πολλά σφάλματα κατά την χρήση τους. Ο σχεδιασμός της περιλαμβάνει δομές που μεταφράζονται αποδοτικά σε τυπικές εντολές μηχανής (machine instructions) και εξ αιτίας αυτού χρησιμοποιείται συχνά σε εφαρμογές που παλιότερα γράφονταν σε συμβολική γλώσσα (assembly language). Αυτό ακριβώς το χαρακτηριστικό της, που έχει σαν συνέπεια και την αυξημένη ταχύτητα εκτέλεσης των εφαρμογών που γράφονται σε αυτή, καθώς και το γεγονός ότι είναι διαθέσιμη στα περισσότερα σημερινά λειτουργικά συστήματα, συνέβαλε κατά πολύ στην καθιέρωση της και την χρήση της για ανάπτυξη λειτουργικών συστημάτων και λοιπών προγραμμάτων συστήματος (system software), αλλά και απλών εφαρμογών. Η C συγκαταλέγεται πλέον στις πιο ευρέως χρησιμοποιούμενες γλώσσες προγραμματισμού όλων των εποχών και πολλές νεώτερες γλώσσες έχουν επηρεαστεί άμεσα ή έμμεσα από αυτήν, συμπεριλαμβανομένων των C++, C#, D, Go, Java, JavaScript, Limbo, LPC, Perl, PHP, Python, καθώς και του κελύφους C (C shell) του Unix. Κάποιες από αυτές τις γλώσσες έχουν επηρεαστεί κυρίως στη σύνταξη τους, με το σύστημα τύπων, τα μοντέλα δεδομένων και το νόημα των εκφράσεων τους να διαφέρουν σημαντικά από την C. Η C++, ειδικά, ξεκίνησε σαν προεπεξεργαστής της C, αλλά έχει εξελιχθεί πλέον σε μια αντικειμενοστραφή γλώσσα, που αποτελεί υπερσύνολο της C.

 Η C είναι μια σχετικά μινιμαλιστική γλώσσα προγραμματισμού. Ανάμεσα στους σχεδιαστικούς στόχους που έπρεπε να καλύψει η γλώσσα περιλαμβανόταν το ότι θα μπορούσε να μεταγλωττιστεί άμεσα με τη χρήση μεταγλωττιστή ενός περάσματος (single-pass compiler) — με άλλα λόγια, ότι θα απαιτούνταν μόνο ένας μικρός αριθμός από εντολές σε γλώσσα μηχανής για κάθε βασικό στοιχείο της, χωρίς εκτεταμένη υποστήριξη στον χρόνο εκτέλεσης. Ως αποτέλεσμα, είναι δυνατό να γραφτεί κώδικας σε C σε χαμηλό επίπεδο προγραμματισμού με ακρίβεια ανάλογη της συμβολικής γλώσσας, στην πραγματικότητα η C ορισμένες φορές αποκαλείται (και χωρίς να υπάρχει πάντα αντιπαράθεση) «συμβολική γλώσσα υψηλού επιπέδου» («high-level assembly») ή «φορητή συμβολική γλώσσα» («portable assembly»). Επίσης, γίνονται αναφορές στη C ως γλώσσα προγραμματισμού μεσαίου επιπέδου. Στη C δεν επιβάλλεται κάποια συγκεκριμένη μορφή στον πηγαίο κώδικα (όπως, για παράδειγμα, συνέβαινε στις αρχικές εκδόσεις της Fortran). Ο προγραμματιστής, χωρίς να αγνοεί φυσικά το συντακτικό της γλώσσας, είναι ελεύθερος να δώσει όποια μορφή θέλει στον κώδικα που γράφει (free-format source). Το ελληνικό ερωτηματικό (;) χρησιμοποιείται ως τερματιστής εντολών (και όχι ως διαχωριστής, όπως στην Pascal, παραδείγματος χάριν) και τα άγκιστρα ({}) χρησιμοποιούνται για την ομαδοποίηση εντολών (όπως τα begin/end στην Pascal). Ακόμα, στη C όλος ο εκτελέσιμος κώδικας περιέχεται σε υπορουτίνες οι οποίες ονομάζονται «συναρτήσεις» (όχι με την αυστηρή έννοια του συναρτησιακού προγραμματισμού). Οι παράμετροι περνιούνται στις συναρτήσεις πάντα με τιμή (pass-by-value). Το πέρασμα με αναφορά (pass-by-reference) γίνεται έμμεσα στην ουσία, περνώντας, ως παραμέτρους των συναρτήσεων, δείκτες στις μεταβλητές των οποίων θέλουμε να αλλάζουμε τις τιμές μέσα από τις συναρτήσεις. Η C έχει ακόμα τα εξής χαρακτηριστικά: Έχει ένα πολύ μικρό σταθερό πλήθος λέξεων-κλειδιών (keywords), το οποίο περιλαμβάνει ένα πλήρες σύνολο δομών/εντολών ελέγχου ροής: for, if/else, while, switch, και do/while, goto. Υπάρχει μόνο ένας χώρος ονομάτων (namespace) και τα ονόματα (μεταβλητών, συναρτήσεων, κ.τ.λ.) που ορίζονται από το χρήστη δεν διακρίνονται με κάποιο τρόπο από τις λέξεις-κλειδιά της γλώσσας. Υπάρχει ένα μεγάλο πλήθος αριθμητικών, σχεσιακών και λογικών τελεστών, όπως οι: +, +=, ++, -, -=, --, *, *=, /, /=, ==, >,>=, <, <=, !=, &, &&, |, ||, ~, κ.ά. Σε μία εντολή μπορεί να γίνουν παραπάνω από μια εκχωρήσεις τιμών. Η τιμή που επιστρέφει μια συνάρτηση, μπορεί να αγνοηθεί εάν δεν χρειάζεται. Ο ορισμός των τύπων των μεταβλητών είναι στατικός και απαραίτητος, αλλά γίνονται έμμεσες μετατροπές από τη γλώσσα. Για παράδειγμα, παραστάσεις με τύπο χαρακτήρα μπορούν να χρησιμοποιηθούν σε σημεία που απαιτείται ακέραιος. Η σύνταξη των δηλώσεων ονομάτων προσομοιάζει την χρήση αυτών μέσα στον εκτελέσιμο κώδικα. Η C δεν έχει ειδική λέξη-κλειδί για τον ορισμό ονομάτων (όπως είναι η "var" στην Pascal, για παράδειγμα) ή συναρτήσεων (όπως η "function", πάλι στην Pascal). Μια γραμμή που ξεκινάει με το όνομα ενός τύπου, εκλαμβάνεται σαν ορισμός μεταβλητής ή συνάρτησης, ανάλογα με τον αν υπάρχουν, ή όχι, παρενθέσεις που περικλείουν (τυπικές) παραμέτρους συνάρτησης. Ο χρήστης μπορεί να ορίσει δικούς του τύπους (και σύνθετους), εάν το επιθυμεί. Μπορεί επίσης να ορίσει και τύπους εγγραφών (structs στη C, records σε άλλες γλώσσες). Μπορούν να οριστούν πίνακες, αν και δεν υπάρχει ειδική λέξη-κλειδί για τον ορισμό τους (όπως το "array" στην Pascal). Η δεικτοδότηση τους γίνεται με χρήση αγκυλών ([]), αν και πολύ συχνά γίνεται χρήση αριθμητικής δεικτών. Το πρώτο στοιχείο κάθε πίνακα δεικτοδοτείται πάντα από το μηδέν (0). Π.χ.: Το στοιχείο month[0] είναι το πρώτο στοιχείο του πίνακα month. Τέλος, δεν υπάρχουν τελεστές για την σύγκριση ή εκχώρηση πινάκων. Είναι δυνατή η δημιουργία απαριθμήσιμων τύπων με τη χρήση της λέξης-κλειδί "enum", οι οποίοι μπορούν να χρησιμοποιηθούν όπου οι ακέραιοι και αντίστροφα. Δεν υπάρχει ιδιαίτερος τύπος για αλφαριθμητικά, τα οποία παραδοσιακά υλοποιούνται και αντιμετωπίζονται σαν πίνακες από χαρακτήρες, και έχουν έναν μηδενικό χαρακτήρα να σημαδεύει το τέλος τους (null-terminated arrays of characters). Είναι δυνατή η άμεση προσπέλαση χαμηλού επιπέδου στη μνήμη του υπολογιστή με τη χρήση δεικτών. Οι υπορουτίνες που δεν επιστρέφουν τιμή ("procedures" σε άλλες γλώσσες) είναι συναρτήσεις που ορίζονται να είναι τύπου "void" (ψευδοτύπος που δείχνει την απουσία επιστρεφόμενης τιμής, αλλά χρησιμοποιείται και για δείκτες που δεν δείχνουν σε αντικείμενο συγκεκριμένου τύπου). Δεν μπορούν να οριστούν συναρτήσεις μέσα σε άλλες συναρτήσεις (εμφωλιασμένες). Οι δείκτες σε συναρτήσεις και δεδομένα επιτρέπουν την υλοποίηση πολυμορφισμού στην πράξη. Ο προεπεξεργαστής της γλώσσας επιτρέπει τον ορισμό μακροεντολών, την συγχώνευση αρχείων πηγαίου κώδικα, καθώς και την μεταγλώττιση υπό συνθήκες. Αρχεία πηγαίου κώδικα μπορούν να μεταγλωττιστούν χωριστά και να συνδεθούν μαζί, ενώ υπάρχει η δυνατότητα ελέγχου της ορατότητας συναρτήσεων και μεταβλητών στα αλλα αρχεία (πέρα από αυτό στο οποίο ορίζονται) με το χαρακτηρισμό τους ως "static" ή "extern". Οι πολύπλοκες λειτουργίες, όπως οι λειτουργίες εισόδου/εξόδου, ο χειρισμός των αλφαριθμητικών, καθώς και οι μαθηματικές συναρτήσεις, έχουν ανατεθεί, με συνεπή τρόπο, στις αντίστοιχες βιβλιοθήκες.Η C δεν διαθέτει κάποιες από τις δυνατότητες νεώτερων γλωσσών, όπως τον προσανατολισμό στα αντικείμενα και την συλλογή απορριμάτων (garbage collection). Σε πρώτη φάση,η C αναπτύχθηκε στα AT&T Bell Labs ανάμεσα στο 1969 και το 1973, σύμφωνα με τον D. Ritchie, η πιο δημιουργική περίοδος υπήρξε το 1972. Η νέα γλώσσα ονομάστηκε "C" λόγω του ότι πολλά από τα χαρακτηριστικά της προήλθαν από μια παλαιότερη γλώσσα, η οποία ονομαζόταν "B". Οι πηγές δεν επιτρέπουν την πλήρη εξακρίβωση για την προέλευση του ονόματος "B" : ο Ken Thompson το παρουσιάζει ως απλούστευση μιας έκδοσης της γλώσσας προγραμματισμού BCPL, αλλά είχε επίσης δημιουργήσει μία γλώσσα που ονομαζόταν Bon προς τιμήν της συζύγου του Bonnie. Μέχρι το 1973, η C είχε γίνει αρκετά ισχυρή και αποτελεσματική, ώστε το μεγαλύτερο μέρος του πυρήνα του UNIX (UNIX kernel), γραμμένο αρχικά σε PDP-11/20 assembly, επανεγγράφηκε σε C. Ήταν ένας από τους πρώτους πυρήνες που υλοποιήθηκε σε μια γλώσσα διαφορετική της assembly. (Προηγούμενα παραδείγματα περιλαμβάνουν το Multics system (γραμμένο σε PL/I), και το MCP (Master Control Program) για το Burroughs B5000 γραμμένο σε ALGOL το 1961.) Το 1978, ο Dennis Ritchie και ο Brian Kernighan δημοσίευσαν την πρώτη έκδοση του βιβλίου "The C Programming Language". Το συγκεκριμένο βιβλίο, γνωστό στους προγραμματιστές της C ως "K&R", χρησίμευσε πολλά χρόνια σαν ανεπίσημος ορισμός της γλώσσας. Η έκδοση της C που περιγράφει αναφέρεται συνήθως ως "K&R C." ή "Common C". (Η δεύτερη έκδοση του βιβλίου καλύπτει το μεταγενέστερο πρότυπο ANSI για τη C (ANSI C standard), βλ. συνέχεια.) Το K&R εισήγαγε τα παρακάτω χαρακτηριστικά στη γλώσσα: Τύποι δεδομένων: εγγραφές (struct), τύποι ακεραίων (long int, unsigned int) Ο τελεστής (operator) =+ αλλάχθηκε σε += για να αποφευχθούν σημασιολογικά διφορούμενες εκφράσεις όπως η i=+10, που μπορούσε να ερμηνευθεί είτε σαν i =+ 10 είτε σαν i = +10.Η K&R C συχνά λογίζεται ως το βασικό μέρος της γλώσσας που πρέπει να υποστηρίζει ένας μεταγλωττιστής της C. Για αρκετά χρόνια, ακόμη και μετά την εισαγωγή της ANSI C, θεωρούνταν ο "ελάχιστος συνήθης παρονομαστής" στον οποίο έπρεπε να προσαρμοστούν οι προγραμματιστές της C σε περιπτώσεις κατά τις οποίες ήταν επιθυμητή η μέγιστη μεταφερσιμότητα (portability), καθώς δεν είχαν ενημερωθεί όλοι οι μεταγλωττιστές για πλήρη υποστήριξη της ANSI C. Επίσης, με προσοχή, ο κώδικας σε K&R C μπορούσε να γραφεί ώστε να είναι σύμφωνος και με το πρότυπο ANSI. Το 1983, το American National Standards Institute (ANSI) όρισε επιτροπή, τη X3J11, για να δώσει ένα σύγχρονο, πλήρη ορισμό της C. Μετά από μακρά και επίπονη επεξεργασία, το πρότυπο (standard) ολοκληρώθηκε το 1989 και επικυρώθηκε ως ANSI X3.159-1989 "Programming Language C". Η συγκεκριμένη έκδοση της γλώσσας ονομάζεται συχνά ANSI C ή, ορισμένες φορές, C89 (για να διαχωρίζεται από τη C99). Το 1990, το πρότυπο ANSI για τη C (με ορισμένες μικρές τροποποιήσεις) υιοθετήθηκε από τον Οργανισμό Διεθνών Προτύπων (International Organization for Standardization (ISO)) ως ISO/IEC 9899:1990. Αυτή η έκδοση καλείται C90. Επομένως, οι όροι "C89" και "C90" αναφέρονται ουσιαστικά στην ίδια γλώσσα. Ένας από τους στόχους της διαδικασίας δημιουργίας του προτύπου ANSI για τη C ήταν να δημιουργήσει ένα υπερσύνολο της K&R C, το οποίο θα απορροφούσε πολλά χαρακτηριστικά που είχαν εισαχθεί στην πορεία. Παρόλα αυτά, η επιτροπή συμπεριέλαβε και ορισμένα νέα χαρακτηριστικά, όπως function prototypes (δανεισμένα από τη C++), και ένα πιο ικανό προεπεξεργαστή (preprocessor). Η σύνταξη για τους ορισμούς παραμέτρων άλλαξε επίσης, ώστε να αντικατοπτρίζει το στυλ της C++. Μετά τη διαδικασία καθορισμού του προτύπου ANSI, ο ορισμός της γλώσσας C παρέμενε σχετικά σταθερός για ορισμένο καιρό, ενώ η C++ συνέχιζε να αναπτύσσεται. (Normative Amendment 1 δημιούργησε μία νέα έκδοση της γλώσσας C το 1995, αλλά σπάνια είναι γνωστή.) Ωστόσο, το πρότυπο επανεξετάστηκε προς το τέλος της δεκαετίας του '90, γεγονός που οδήγησε στην έκδοση του ISO 9899:1999 το 1999. Το πρότυπο αυτό συχνά αναφέρεται ως "C99". Υιοθετήθηκε ως πρότυπο ANSI το Μάρτιο του 2000. Ο GCC και μερικοί άλλοι C compilers υποστηρίζουν πλέον τα περισσότερα χαρακτηριστικά του C99. Ωστόσο, υπάρχει μικρότερη υποστήριξη από εταιρίες όπως η Microsoft και η Borland που εστίασαν περισσότερο στη C++, καθώς η C++ παρέχει παρόμοια λειτουργικότητα και συχνά ασύμβατους τρόπους (π.χ., η complex template class). Ο Brandon Bray από τη Microsoft είπε "Σε γενικές γραμμές, έχουμε δει μικρές απαιτήσεις για πολλά χαρακτηριστικά του C99. Μερικά χαρακτηριστικά έχουν μεγαλύτερη ζήτηση από άλλα, και θα τη λάβουμε υπόψιν μας σε μελλοντικές εκδόσεις εφόσον είναι συμβατά με τη C++."Ακόμη και ο GCC με την εκτεταμένη υποστήριξη του C99 ακόμη δεν προσεγγίζει μια πλήρως συμβατή υλοποίηση, ορισμένα χαρακτηριστικά-κλειδιά λείπουν ή δεν λειτουργούν σωστά. Το 2007 άρχισαν οι εργασίες για μια ακόμα αναθεώρηση του προτύπου της C, ανεπίσημα αποκαλούμενο "C1X" ως και την επίσημη δημοσίευση του στις 8/12/2011. Η επιτροπή προτύπων της C έθεσε ως κατευθυντήριες γραμμές τον περιορισμό υιοθεσίας νέων χαρακτηριστικών τα οποία δεν έχουν δοκιμαστεί απο υπάρχουσες υλοποιήσεις. Το πρότυπο C11 προσθέτει πολυάριθμα χαρακτηριστικά στην C και στην βιβλιοθήκη συμπεριλαμβομένων type generic macros, anonymoys structures, βελτιωμένη υποστήριξη Unicode, atomic operations, multi-threading και συναρτήσεις bounds-checked. Επίσης κάνεις κάποιες προαιρετικές αναθεωρήσεις στην βιβλιοθήκη του C99 και βελτιώνει την συμβατότητα με την C++. Η πρότυπη μάκρο __STDC_VERSION__ προσδιορίζεται ως 201112L για να δηλώσει οτί η υποστήριξη για το C11 είναι διαθέσιμη. Δημοσιευμένο το Ιούνιο του 2018, το C18 είναι το τρέχον πρότυπο για τη γλώσσα προγραμματισμού C. Δεν εισάγει νέα χαρακτηριστικά στη γλώσσα αλλά μόνο τεχνικές διορθώσεις και διευκρινίσεις σε ατέλειες του προτύπου C11. Η πρότυπη μάκρο __STDC_VERSION__ προσδιορίζεται ως 201710L. Πρόγραμμα σε C που εκτυπώνει στο τερματικό "Hello world!": C πρότυπη βιβλιοθήκη C++ C είσοδος/έξοδος αρχείων Brian W. Kernighan, Dennis M. Ritchie. "Η Γλώσσα Προγραμματισμού C", Prentice-Hall (Ελληνική μετάφραση, εκδόσεις Κλειδάριθμος), 1988. Νίκος Μ. Χατζηγιαννάκης. "Η γλώσσα C σε βάθος", Εκδόσεις Κλειδάριθμος (Ελληνικά) http://c.bytes.gr Κωνσταντίνος Φ. Γραίκας. "Γραμματική και Συντακτικό της ANSI C". Εκδόσεις Κλειδάριθμος 2007, σελ. 296. Δημήτριος Καρολίδης. "Μαθαίνετε εύκολα C", Εκδόσεις Άβακας, 2013. Γεώργιος Σ. Τσελίκης, Νικόλαος Δ. Τσελίκας "C: Από τη Θεωρία στην Εφαρμογή"], Γ' Έκδοση, Ιούλιος 2016, σελ. 832, ISBN 978-960-93-1961-4. www.c4all.gr/ Θεόδωρος Αλεβίζος. "Προγραμματισμός με τη γλώσσα C++", 2015 (Διαθέσιμο δωρεάν) Πάρις Μαστοροκώστας. "Διαδικαστικός προγραμματισμός – Η γλώσσα C", 2015. (Διαθέσιμο δωρεάν) C programming — Εγχειρίδιο της C για αρχάριους (Αγγλικά) Programming in C : A tutorial — Εγχειρίδιο της C από τον Brian Kernighan (σε pdf) (Αγγλικά) Από τη B στη C (Αγγλικά) [2] - Το άρθρο της αγγλικής Wikipedia για τη C. (Αγγλικά) C (γλώσσα προγραμματισμού) στο Curlie