migf1 Δημοσ. 31 Μαΐου 2014 Δημοσ. 31 Μαΐου 2014 Καταρχήν μην απογοητεύεσαι! Σε αυτή τη φάση δεν νομίζω πως θα σε βοηθήσει και πολύ να δεις τα low-level implementations της libc. Αντίθετα, νομίζω πως το βιβλίο που σου προτείναμε με τον gon32 είναι πολύ πιο... eye opener! ΥΓ. Για beginners πάντως εγώ προτείνω αυτό εδώ: http://www.amazon.com/Programming-Modern-Approach-2nd-Edition/dp/0393979504 (μαζί με το άλλο κάνουν φοβερό... σετάκι )
gon1332 Δημοσ. 31 Μαΐου 2014 Δημοσ. 31 Μαΐου 2014 οκ οσο και να απογοητευτηκα απο τα λεγομενα, καλυτερα μια φαπα τωρα παρα ποτε. θα το εχω υποψιν μου ολο αυτο το κραξιμο με την καλη εννοια βεβαια, καλυτερα αυτη η εκρηξη απαντησεων παρα σε ψευτικες ελπιδες. σαφως δεν ξεφιλιζα τα κεφαλαια ετσι απλα, σε καθε κεφαλαιο αφιερωνα αρκετο απο το χρονο μου στην επιλυση των ασκησεων μεχρι που εφτασα στο κεφαλαιο με την διαχειρηση των αρχειων!!! απο αυτο το κεφαλαιο και περα ας πουμε μου γεννηθηκαν αυτες οι αποριες και οι τροποι λειτουργιας τους. Παραδειγμα οι συναρτησεις στο κεφαλαιο των strings (αυτες που ειχε το βιβλιο) θα μπορουσα να τις κατασκευαζω γιατι ειχε μια λογικη, ενω οι συναρτησεις στα αρχεια (αυτες που εχει το βιβλιο) ναι μεν καταλαβαινω τι κανει η καθε μια αλλα δυσκολευομαι στην κατανοηση. Βεβαιος καποιος ανεφερ μερικα πραγματα για αυτες τις συναρτησεις οι οποιες μπορω να πως καπως με βοηθησαν. Υ.Σ.Το βιβλιο "η γλωσσα C σε βαθος" μην σας ξεγελαει ο τιτλος αναφερεται σε beginners, ηταν και το πρωτο προτεινομενο βιβλιο του 1ου εξαμηνου. Έχεις παρακολουθήσει τα μαθήματα των αλγορίθμων και δομών δεδομένων; Είναι σημαντικά μαθήματα για τον προγραμματισμό. Θα μπορούσες να εξασκηθείς δημιουργώντας κάποια περίπλοκη δομή. Θα δεις ότι είναι challenging. Αξίζει. Το βιβλίο που σου προτείναμε με τον migf1, αναφέρεται σε άτομα τα οποία έχουν προπτυχιακό επίπεδο γνώσεων. Θα μπορούσες να το ξεκινήσεις. Αν δε μπορείς να το ακολουθήσεις, τότε συνέχισε με τα βασικά μέχρι να νιώσεις έτοιμος για τη βουτιά.
Εγω ειμαι ρε Δημοσ. 31 Μαΐου 2014 Μέλος Δημοσ. 31 Μαΐου 2014 εε οχι το μαθημα αλγοριθμοι και δομες δεδομενων ακομα δεν εχω διδαχθει, αλλα το βιβλιο που μου προτινατε το κατεβασα(αγγλικη εκδοση).παντως σας ευαχρηστω ολους
AllCowsEatGrass Δημοσ. 31 Μαΐου 2014 Δημοσ. 31 Μαΐου 2014 Έχεις παρακολουθήσει τα μαθήματα των αλγορίθμων και δομών δεδομένων; Είναι σημαντικά μαθήματα για τον προγραμματισμό. Θα μπορούσες να εξασκηθείς δημιουργώντας κάποια περίπλοκη δομή. Θα δεις ότι είναι challenging. Αξίζει. +1 ! Αν έχεις αφιερώσει χρόνο στη γλώσσα όπως λες, τότε πιστεύω το να αρχήσεις να φτιάχνεις κάποιες δομές δεδομένων θα σε βοηθήσει πολύ. Ψάξε για παράδειγμα ας πούμε τι είναι ένα binary search tree και προσπάθησε να το υλοποιήσεις μόνος σου. Είναι αρκετά challenging να το κάνεις σωστα.
imitheos Δημοσ. 31 Μαΐου 2014 Δημοσ. 31 Μαΐου 2014 (επεξεργασμένο) οκ οσο και να απογοητευτηκα απο τα λεγομενα, καλυτερα μια φαπα τωρα παρα ποτε. θα το εχω υποψιν μου ολο αυτο το κραξιμο με την καλη εννοια βεβαια, καλυτερα αυτη η εκρηξη απαντησεων παρα σε ψευτικες ελπιδες.Δεν είπα αυτά που είπα για να σου ρίξω φάπα απλά αυτά που έλεγες (παραβλέποντας την ορθογραφία ) ήταν αντικρουόμενα. Όπως είπανε και τα άλλα παιδιά δεν θα σε βοηθήσει και τόσο να μάθεις πως δουλεύει σε χαμηλό επίπεδο η fopen όσο να μάθεις ένα τρόπο σκέψης και υλοποίησης ενός αλγορίθμου. Παραδειγμα οι συναρτησεις στο κεφαλαιο των strings (αυτες που ειχε το βιβλιο) θα μπορουσα να τις κατασκευαζω γιατι ειχε μια λογικη, ενω οι συναρτησεις στα αρχεια (αυτες που εχει το βιβλιο) ναι μεν καταλαβαινω τι κανει η καθε μια αλλα δυσκολευομαι στην κατανοηση. Βεβαιος καποιος ανεφερ μερικα πραγματα για αυτες τις συναρτησεις οι οποιες μπορω να πως καπως με βοηθησαν. Ειδικά οι συναρτήσεις αρχείων δεν είναι και τόσο ορισμένο τι κάνουν γιατί το κάθε λειτουργικό σε χαμηλό επίπεδο έχει διαφορετική λειτουργία. Μια και φαγώθηκες ας δούμε πολύ επιγραμματικά και μπακάλικα τι κάνουν. FILE *fopen(const char *path, const char *mode); size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);Εδώ είναι η σύνταξη των κλασικών "υψηλού επιπέδου" συναρτήσεων fopen και fread. Αυτές οι συναρτήσεις δουλεύουν πάντα με τον τύπο FILE για τον οποίο δεν γνωρίζεις τι είναι (συνήθως είναι δομή με διάφορα πεδία). Εκτός από αυτές τις πρότυπες συναρτήσεις, υπάρχει και μια σειρά "χαμηλού επιπέδου" συναρτήσεων που διαφοροποιούνται σε κάθε λειτουργικό και που χρησιμοποιούν handles. int open(const char *pathname, int flags); ssize_t read(int fd, void *buf, size_t count);Όπως βλέπεις, η open χρειάζεται να της δώσεις υπό μορφή ακεραίου τις διάφορες flags αντί για το string (πχ "rb") που χρησιμοποιείς στην fopen και αντί για τύπο FILE επιστρέφει ένα ακέραιο handle. Η open είναι πιο δυνατή και υποστηρίζει περισσότερες επιλογές ανάλογα με το λειτουργικό και το σύστημα αρχείων φυσικά. Αντίστοιχα, η read δουλεύει και αυτή με handle και με ένα μέγεθος αντί για δύο που έχει η fread. Όπως σου είπε ο defacer, δεν έχει πολύ νόημα να ασχοληθούμε με το τι κάνει η fread γιατί από libc σε libc μπορεί να κάνει διαφορετικά πράγματα και επίσης η χαμηλού επιπέδου συνάρτηση που θα καλεί θα έχει διαφορετική συμπεριφορά από λειτουργικό σε λειτουργικό. Έτσι αυτό που θα περιγράψω εγώ είναι τι θα μπορούσε πιθανώς να κάνει μία fread / fopen. FILE *fopen(const char *path, const char *mode) { FILE *f; int fd; int flags; if ((path == NULL) || (mode == NULL)) return NULL; flags = parse_mode(mode); fd = open(path, flags); if (fd < 0) return(NULL); f = alloc_file_mem(); f->handle = fd; f->flags = flags; f->buf = buf_alloc(); f->bytesleft = bufsiz; f->whatever = _deina; } Το πρώτο που λογικά κάνει η fopen είναι μια σειρά ελέγχων. Το "path" που έδωσες είναι κάποιο σωστό string ή μήπως είναι NULL και το ίδιο για το mode. Μετά θα πρέπει να κάνει parse το string που δίνεις για κατάσταση ανοίγματος και να το μετατρέψει στο ακέραιο flags ώστε να μπορεί να καλέσει την open. Τότε το λειτουργικό θα ελέγξει για permissions και λοιπές εργασίες που έχει να κάνει και αν όλα είναι σωστά, θα σου επιστρέψει ένα ακέραιο handle (πχ το 5). Σε αυτό το σημείο το αρχείο έχει ανοιχτεί αλλά για χρήση με την read οπότε η fopen θα δεσμεύσει μνήμη για ένα αντικείμενο FILE και θα συμπληρώσει τα διάφορα πεδία της δομής με το handle που έλαβες και ό,τι άλλο χρειάζεται. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { size_t total; size_t bytes; if (stream == NULL) return 0; if (uperxeilisi) return 0; total = size * nmemb; while (total > 0) { // an den exei dedomena to buffer tou leitoyrgikoy gemise to if (stream->bytesleft == 0) { read(stream->handle, stream->buf, bufsiz); stream->bytesleft=bufsiz; } bytes = (stream->bytesleft > total) ? total : stream->bytesleft; // antigrafoyme apo to buffer toy leitoyrgikou se ayto toy xrhsth osa bytes xreiazontai // kai allazoyme tous deiktes memcpy(ptr, stream->buf, bytes); ptr += bytes; total -= bytes; stream->bytesleft -= bytes; } return nmembl; } Το ίδιο πράγμα θα κάνει και η fread. Όπως είπαμε, η fread δέχεται δύο ορίσματα και διαβάζει τόσα bytes όσο το γινόμενό τους. Αν κάποιος όμως δώσει μεγάλους αριθμούς, μπορεί να υπάρχει υπερχείλιση στο γινόμενο. Έτσι μια υλοποίηση μπορεί να ελέγχει πριν να κάνει τον πολλαπλασιασμό ενώ μια άλλη να μην ελέγχει. Επίσης διαφοροποίηση στη συμπεριφορά μπορεί να υπάρξει και σε σχέση με τα size, nmemb αλλά ας μην μπούμε εκεί. Μετά θα διαβάσει τον αριθμό bytes που έχει ζητηθεί θα τα αντιγράψει στην μεταβλητή σου και θα επιστρέψει. Για την ακρίβεια επειδή μιλάμε για buffered είσοδο θα διαβάσει αν μπορεί πιο πολλά από όσα ζητάς και θα τα αποθηκεύσει προσωρινά σε ένα buffer του λειτουργικού οπότε κάθε φορά που τρέχει την fread, αν τα δεδομένα υπάρχουν σε αυτό το buffer θα τα παίρνεις από εκεί. Edit: Στην fread δεν ελέγχω για προβλήματα και να επιστρέψει η συνάρτηση νωρίτερα ούτε αλλάζει το εσωτερικό buffer ώστε να δείχνει εκεί που πρέπει αλλά αυτά να ήταν μόνο τα προβλήματα Όσον αφορά την malloc και αυτό είναι μεγάλο κεφάλαιο μια και έχουν υπάρξει καμιά 10αριά "καλές" υλοποιήσεις και καμμιά 100αριά hobby υλοποιήσεις με την κάθε μία να συμπεριφέρεται διαφορετικά. Ένας τρόπος λειτουργίας της θα ήταν να δεσμεύει σελίδες μνήμης από το λειτουργικό (συνήθως όταν λέμε μία σελίδα εννοούμε 4KB) και να τις χωρίζει σε περιοχές. Έτσι να έχει μια περιοχή των 2KB, μία του 1KB, μία του 512B, κτλ έτοιμες για χρήση. Έτσι για λόγους ταχύτητας και εφόσον υπάρχει αρκετή μνήμη ελεύθερη, δεν κάθεται να χωρίσει τις περιοχές ξανά και σου δίνει την αμέσως μεγαλύτερη. Όταν εσύ ζητήσεις 326 bytes θα σου δώσει την περιοχή των 400bytes που είχε έτοιμη. Όταν μετά τρέξεις free, μαρκάρει ότι η περιοχή είναι ξανά ελεύθερη και θα την δώσει αλλού. Υπάρχουν πολλές ιστοσελίδες (στα αγγλικά οι πιο πολλές) που αναλύουν λεπτομερώς τι κάνει η τάδε υλοποίηση malloc. Φυσικά η εξήγησή μου δεν είναι και η καλύτερη αλλά σε ένα post είναι δύσκολο να περιγράψεις ένα τόσο μεγάλο κεφάλαιο και με τόσες διαφοροποιήσεις. Επεξ/σία 31 Μαΐου 2014 από imitheos 3
Εγω ειμαι ρε Δημοσ. 31 Μαΐου 2014 Μέλος Δημοσ. 31 Μαΐου 2014 μαλιστα σε ευχαρηστω πολυ, αρκετα κατανοητοι ο κωδικες και η επεξηγησηλυθηκαν αρκετες αποριες!!! γενικα ομως δημιουργουν οι προγραμματιστες δικες τους ας πουμε fopen() (π.χ. fmitsos() )που στις δικες τους συναρτησεις να εχουν αλλες χαμηλου επιπεδου, ή ειναι εξαιρετικα χρονοβορο και δυσκολο ή να κατσω στα αυγα μου προς το παρον? Υ.Σ. Τελικα βρηκαμε καποια ακρη EDIT: δηλαδη για την fopen(), το ζουμι κρυβεται στην συναρτηση open() η οποια ειναι χαμηλότερου επιπεδου.
imitheos Δημοσ. 31 Μαΐου 2014 Δημοσ. 31 Μαΐου 2014 γενικα ομως δημιουργουν οι προγραμματιστες δικες τους ας πουμε fopen() (π.χ. fmitsos() ) που στις δικες τους συναρτησεις να εχουν αλλες χαμηλου επιπεδου, ή ειναι εξαιρετικα χρονοβορο και δυσκολο ή να κατσω στα αυγα μου προς το παρον? Σε χαμηλό επίπεδο έχεις μια σειρά συναρτήσεων που σου παρέχει το λειτουργικό. Δεν υπάρχουν δηλαδή 45 χαμηλού επιπέδου τρόποι για να επιλέξεις ποιον θέλεις (αν κατάλαβα καλά το "άλλες χαμηλού επιπέδου"). Αν σου αρκούν οι fτάδε συναρτήσεις τότε χρησιμοποιείς αυτές. Αν όχι πας στο πιο χαμηλό επίπεδο. Τι κάνει ο κάθε προγραμματιστής δεν μπορώ να ξέρω αλλά κάποια projects χρησιμοποιούν τον preprocessor ώστε να δημιουργήσουν όχι δικές τους συναρτήσεις αλλά wrappers που στο εκάστοτε λειτουργικό να καλούν την εκάστοτε συνάρτηση (πχ open σε *nix και _open σε windows ή κάτι τέτοιο). δηλαδη για την fopen(), το ζουμι κρυβεται στην συναρτηση open() η οποια ειναι χαμηλότερου επιπεδου. Έτσι το σκέφτηκα εγώ σαν ένα πιθανό σενάριο και σαν εύκολο παράδειγμα. Μπορεί 10 υλοποίησεις libc να τρέχουν από κάτω την open όπως το έγραψα ή μπορεί να μην το κάνει καμμιά γιατί είναι χαζός τρόπος και το λειτουργικό παρέχει ένα πιο γρήγορο τρόπο. Εσύ ξέρεις ότι η C σου παρέχει μια συνάρτηση fopen που έχει μια κάποια συμπεριφορά. Το πώς υλοποιείται εσωτερικά είναι στη κρίση της υλοποίησης της libc για αυτό και τα παιδιά σου είπαν ότι δεν έχει νόημα να το ψάξεις.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα