Ilias95 έγραψε:
Κατάλαβα και την χρησιμότητα των const και την διαφορά τους με τις σταθερές που ορίζονται με #define.
Βασικά είναι 2 τελείως διαφορετικά πράγματα, απλά μια (από τις πολλές) χρήση τους συμπίπτει.. ο ορισμός μιας σταθερής τιμής. Το const δεν υπήρχε αρχικά στη γλώσσα.
Κοίταξα τώρα στο βιβλίο και είδα πως αρχικά αναφέρεται στο keyword
const στο 8ο κεφάλαιο, εκεί που λέει για
constant arrays, και κατόπιν παραπέμπει στη σελίδα 466 όπου αναλύει τις διαφορές με τα
#define (btw, αυτό που γράφει εκεί, πως τα
#define δεν εμφανίζονται στον debugger, ο gdb το έχει λύσει το θέμα αυτό, αν κάνεις compile τα προγράμματα σου με το flag -g3 στον gcc (νομίζω και με -g2 και -g1, δεν είμαι σίγουρος).
Για να σου εντυπωθεί, σκέψου πως όποια μεταβλητή την ορίσεις με
const μπροστά, την θέτεις
μόνιμα σε κατάσταση
read-only έγραψε:Ορισμένες απορίες προκύπτουν σχετικά με τα macros και για ποιο λόγο να τα προτιμήσουμε έναντι συναρτήσεων που θα κάνουν ακριβώς την ίδια δουλειά, αλλά πιθανότατα θα βρω τις απαντήσεις στο βιβλίο μόλις φτάσω στα κατάλληλα κεφάλαια.
Οι βασικές τους διαφορές είναι δυο:
α) στα macros ο compiler δεν τσεκάρει για τους τύπους των ορισμάτων (άρα δεν μπορεί να πιάσει απροσεξίες σου)
β) με εξαίρεση τα ονόματα των ορισμάτων τους (που προσαρμόζονται αυτόματα κατά το κάλεσμά τους, όπως και στις συναρτήσεις) το κυρίως σώμα των macros είναι ένα απλό search & replace στα σημεία του κώδικα που καλείς το macro. Είναι δηλαδή σαν αν έχεις γράψει χειροκίνητα τον κώδικα του macro σε όλα τα σημεία στα οποία το καλείς. Άρα τα macros εκτελούνται ταχύτερα από ότι οι συναρτήσεις, επειδή δεν δημιουργείται νέο stack frame στο run-time, ούτε προφανώς σώζονται/φορτώνονται/μετακινούνται κλπ τα ορίσματα σε μνήμη ή σε registers.
Ας πάρουμε για παράδειγμα ότι χρειάζεσαι να συγκρίνεις δυο τιμές και να κρατάς την μικρότερη ανάμεσά τους, σε διάφορα σημεία του κώδικά σου.
Αν το υλοποιήσεις με συνάρτηση...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
int min(const int x, const int y)
{
return x < y ? x : y;
}
έχεις ως υπέρ ότι αν καλέσεις τη συνάρτηση με 2 τιμές ή μεταβλητές που ΔΕΝ είναι τύπου
int, ο compiler θα το "πιάσει" και θα βγάλει σφάλμα (type-checking). Το ίδιο θα πράξει αν είναι int μονάχα το ένα από τα δυο ορίσματα.
Παράλληλα έχεις το μειονέκτημα πως αν η σύγκριση που χρειάζεσαι θες να μπορεί να εφαρμοστεί σε τιμές/μεταβλητές άλλου τύπου (π.χ. float) τότε θα πρέπει να φτιάξεις κι άλλη συνάρτηση, ειδικά για σύγκριση μεταξύ float, άρα 2 βασικά ίδιες συναρτήσεις με μόνη διαφορά τον τύπο (ορισμάτων & επιστροφής)...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
int min_int(const int x, const int y)
{
return x < y ? x : y;
}
float min_float(const float x, const float y)
{
return x < y ? x : y;
}
Αν το υλοποιήσεις με macro...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
#define MIN(x,y) ( (x) < (y) ? (x) : (y) )
έχεις τα ακριβώς αντίθετα πλεονεκτήματα & μειονεκτήματα. Μπορείς να συγκρίνεις ελεύθερα με το ίδιο ακριβώς macro 2 μεταβλητές/τιμές ίδιου τύπου, αλλά ακόμα κι αν του περάσεις το ένα όρισμα ως
float και το άλλο ως
char, όχι μόνο δεν θα το "πιάσει" ο compiler αλλά στο run-time θα εκτελεστεί κανονικά το macro... το πόσο αξιόπιστη όμως θα είναι η σύγκριση και κυρίως τι θα επιστρέψει το γνωρίζει μονάχα ο καλός Θεούλης

έγραψε:Ευχαριστώ πολύ για τις αναλύσεις!
Τίποτα ρε συ
