Αυτά είναι !!!

Ότι απορίες έχετε, όσο "χαζές" κι αν τις θεωρείτε παρακαλώ ποστάρετέ τες δημόσια σε αυτό το νήμα. ώστε να επωφεληθούν από τυχόν σωστές απαντήσεις κι άλλα παιδιά της κοινότητας! Να ξέρετε πως ΔΕΝ υπάρχουν χαζές ερωτήσεις (μόνο χαζές απαντήσεις υπάρχουν).
Ειδικά στη C, ακόμα και οι πιο φαινομενικά "αφελείς" απορίες μπορούν να αποδειχτούν σωστά διαμάντια για την επεξήγηση βασικών αρχών που διέπουν τη γλώσσα.
Ήδη έχω δεχτεί pm με ερωτήσεις, τις οποίες υποθέτω ο αποστολέας τους μάλλον "ντρέπεται" να τις παραθέσει δημόσια, αλλά εγώ τις θεωρώ πολύ σημαντικές για να τις απαντήσω ιδιωτικά.
Χωρίς λοιπόν να αποκαλύψω το nickname του αποστολέα, τις παραθέτω με την εξήγησή τους και θα παρακαλούσα στο εξής να τις ποστάρετε απευθείας εδώ. Είμαστε εδώ για να αλληλο-βοηθιόμαστε, δεν κάνουμε διαγωνισμό ποιος ξέρει τα περισσότερα... οπότε δεν υπάρχει απολύτως κανένας λόγος πιστεύω να μην παραθέτουμε δημόσια τις απορίες μας.
Ξεκινώ λοιπόν...
έγραψε:Μήπως ξέρεις τι θα πει macro;
Είναι ότι ορίζεις με #define στην αρχή του προγράμματος (συνήθως ακέραιες σταθερές, αλλά μπορείς να ορίσεις οτιδήποτε). Αυτό που συμβαίνει είναι πως ότι ορίσεις με #define πάει και αντικαθιστά στο υπόλοιπο πρόγραμμα το όνομα του #define με το απόσπασμα κώδικα που αντιστοιχεί στο #define.
Π.χ. αν ορίσεις...
- Κώδικας: Επιλογή όλων
#define MAXINPUT 100
#define ASKUSERNAME printf("Pws se lene? \n")
τότε στον υπόλοιπο κώδικα του προγράμματός σου μπορείς να γράφεις MAXNAME αντί για το νούμερο 100 και να γράφεις ASKUSERNAME αντί για printf("Pws se lene? \n")
έγραψε:Επίσης έχουμε αυτόν τον κώδικα ο οποίος τυπώνει ό,τι του δίνεις.
- Κώδικας: Επιλογή όλων
#include <stdio.h>
/* copy input to output; 1st version */
main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
Λοιπόν: το getchar παίρνει έναν χαρακτήρα έτσι; Πώς γίνεται και δουλεύει το πρόγραμμα όταν βάζω ολόκληρη λέξη;
Επειδή το 2ο getchar() το έχει μέσα σε βρόγχο επανάληψης (loop) στο while-loop. Οπότε με το 1ο getchar ( έξω από το loop ) διαβάζει τον 1ο χαρακτήρα και με το 2ο getchar (μέσα στο loop) διαβάζει όλους τους υπόλοιπους, έναν τη φορά.
έγραψε: Επίσης και να παίρνει η c είναι int, κρατά μόνο έναν χαρακτήρα και το putchar παίρνει ένα νούμερο και το μετατρέπει σε χαρακτήρα σύμφωνα με το ASCII.Μπορείς να μου το εξηγήσεις;
Αυτό είναι λίγο πιο δύσκολο στην κατανόησή του. Βασικά η C είναι χαλαρή γλώσσα σε ότι αφορά τους τύπους των μεταβλητών (loose data types). Σε αφήνει δηλαδή να μετατρέπεις τον τύπο μιας μεταβλητής σε άλλον τύπο, και αφήνει επάνω σου την ευθύνη οι δυο αυτοί τύποι να βρίσκονται σε κάποιου είδους αντιστοιχία μεταξύ τους.
Το πιο συχνά χρησιμοποιούμενο τέτοιο παράδειγμα είναι η μετατροπή μεταξύ των τύπων int και char. Μπορείς να θεωρήσεις πως οι τύποι char και int αντιστοιχούν μεταξύ τους, με την προϋπόθεση πως οι τιμές τους δεν ξεπερνάνε την μέγιστη τιμή που μπορεί να απεικονιστεί μέσα σε ένα byte. Οι τιμές που μπορούν να απεικονιστούν μέσα σε ένα byte είναι από 0 έως 255 αν μιλάμε για αριθμούς χωρίς πρόσημο (unsigned) και από -127 έως 127 αν μιλάμε για αριθμούς με πρόσημο (signed).
Το στάνταρ της γλώσσας
εγγυάται πως οι μεταβλητές τύπου char καταλαμβάνουν
ακριβώς 1 byte, ενώ για τους int εγγυάται πως καταλαμβάνουν
τουλάχιστον 2 bytes (μπορεί να πιάνουν και 4 ή 8 bytes, ανάλογα την αρχιτεκτονική της πλατφόρμας, σίγουρα όμως πιάνουν τουλάχιστον 2 bytes)
Ένας char λοιπόν μπορεί να δεχτεί τιμές από -127 έως 127 (ενώ ένας unsigned char μπορεί να δεχτεί τιμές από 0 έως 255). Αν είμαστε βέβαιοι πως η τιμή που δίνουμε σε έναν int δεν ξεπερνάει το 127, τότε μπορούμε να τον διαχειριστούμε σαν ήταν char.
Τρέξτε για παράδειγμα τον παρακάτω κώδικα:
- Κώδικας: Επιλογή όλων
int c = 97;
printf("c as int = %d\n", c);
printf("c as char = %c\n", c);
Ορίσαμε τον c να είναι int με τιμή 97. Στο 1ο printf τον τυπώσαμε σαν int και μας τύπωσε 97, ενώ στο 2ο printf τον τυπώσαμε σαν char και μας τύπωσε το γράμμα a. Κουφό!
Όχι και τόσο, για όσους γνωρίζουν πως στη C όλοι οι χαρακτήρες κονσόλας αντιστοιχούν
εξ' ορισμού σε ακέραιους αριθμούς, σύμφωνα με τον
πίνακα ASCII. Ακολουθήστε το link και θα διαπιστώσετε πως όντως ο δεκαδικός αριθμός 97 αντιστοιχεί στο πεζό λατινικό γράμμα: a.
Τροποποιήστε ελαφρώς τον παραπάνω κώδικα ως εξής:
- Κώδικας: Επιλογή όλων
char c = 'a';
printf("c as int = %d\n", c);
printf("c as char = %c\n", c);
Αυτή τη φορά ορίσαμε τον c να είναι char με τιμή 'a' (που σημαίνει το λατινικό πεζό γράμμα: a) και του είπαμε ξανά να το τυπώσει πρώτα σαν int και κατόπιν σαν char. Το αποτέλεσμα είναι
ακριβώς το ίδιο με πριν!
Άρα λοιπόν οι char και int βρίσκονται σε αντιστοιχία στην C, όσο η τιμή τους χωράει μέσα σε ένα byte. Επί της ουσίας, το: char c = 'a'; μετατρέπεται έτσι κι αλλιώς εσωτερικά σε: int c = 97;
Πιο συγκεκριμένα, όλες οι τιμές χαρακτήρων (που περικλείονται σε μονά εισαγωγικά) μετατρέπονται έτσι κι αλλιώς στον int που τους αντιστοιχεί στο ASCII table.
Για του λόγου το αληθές, τρέξτε τον παρακάτω κώδικα:
- Κώδικας: Επιλογή όλων
int c = 'a';
printf("c as int = %d\n", c);
printf("c as char = %c\n", c);
Θα τυπώσει ακριβώς ότι και οι 2 προηγούμενοι!
Στη C δουλεύει ακόμα κι αυτό:
- Κώδικας: Επιλογή όλων
char c = 97;
printf("c as int = %d\n", c);
printf("c as char = %c\n", c);
Έχει επίσης ενδιαφέρον να δούμε τι θα γίνει αν δώσουμε στο c τιμή που δεν χωράει σε ένα byte. Ο τύπος char είναι ισοδύναμος με signed char, δηλαδή μπορεί να πάρει και πρόσημο, δηλαδή αρνητικές και θετικές τιμές (σημείωση: όλοι οι τύποι στη C αν δεν γράψουμε τη λέξη unsigned μπροστά από το όνομά του τύπου θεωρούνται αυτόματα signed, δηλαδή με πρόσημο ).
Άρα στον κώδικά μας, οι "έγκυρες" τιμές που μπορούμε να δώσουμε στη μεταβλητή char c είναι από -127 έως 127 (αυτές χωράνε σε ένα byte με πρόσημο). Κι επειδή ο πίνακας ASCII ξεκινάει από το 0, στην πράξη οι έγκυρες τιμές που μπορούμε να δώσουμε στη μεταβλητή char c είναι από 0 έως 127 (δηλαδή αν δείτε τον πίνακα ASCII, είναι από τον χαρακτήρα (null) μέχρι τον χαρακτήρα DEL... και οι δύο αυτοί χαρακτήρες, όπως κι αρκετοί ακόμα είναι non-printable... δεν τυπώνουν δηλαδή κάτι στην οθόνη... π.χ. ο χαρακτήρας 127, ο DEL, άμα τον τυπώσετε στην οθόνη θα συμπεριφερθεί σαν να είχατε πατήσει στην κονσόλα το πλήκτρο DEL στο πληκτρολόγιό σας).
Οπότε τι θα γίνει άραγε αν στον παραπάνω κώδικα δώσουμε στον c την τιμή 128;
Αυτό που θα γίνει είναι πως η C θα τυπώσει τον 1ο από τους χαρακτήρες του λεγόμενου Extended ASCII Table που περιέχει χαρακτήρες από το 128 έως το 255. Αυτοί οι χαρακτήρες ΔΕΝ είναι στάνταρ, εξαρτώνται από την κωδικοσελίδα της γραμματοσειράς που έχετε φορτωμένη στο τερματικό σας.
Αντίθετα, οι χαρακτήρες από το 0 έως το 127 είναι εγγυημένα οι ίδιοι σε όλες τις κωδικοσελίδες, δείτε για παράδειγμα το ASCII Table των κωδικοσελίδων:
MS-DOS Codepage 737 (Greek IBM PC) και
Windows 1253 (Greek) (από τον χαρακτήρα 128 έως το 255 διαφέρουν και διαφέρουν πολύ).
Αν έχετε σκοπό να διαχειριστείτε χαρακτήρες πάνω από το 127 του ASCII Table, προτιμήστε τη μεταβλητή c να τη δηλώσετε ως int, επειδή όπως είπαμε οι char μπορούν να δεχτούν από -127 μέχρι 127 (στους σύγχρονους compilers θα σας δουλέψει και με char, με εσωτερικές μετατροπές οι οποίες όμως δεν είναι στάνταρ σε όλους τους compilers... σε τέτοιες περιπτώσεις οι καλοί compilers σας βγάζουν warning για "char overflow" πριν προβούν στην εσωτερική μετατροπή).