rafail1994 Δημοσ. 1 Μαΐου 2013 Μέλος Δημοσ. 1 Μαΐου 2013 Έριξα μια ματιά στο google για την δομή που είπες αλλά ακόμη δεν την έχουμε κάνει
παπι Δημοσ. 1 Μαΐου 2013 Δημοσ. 1 Μαΐου 2013 καλα δες μονο το pass by pointer. Αυτο ζηταει η ασκηση, δηλαδη το πως θα "επιστρεψεις" πραγματα χωρις την return
albNik Δημοσ. 1 Μαΐου 2013 Δημοσ. 1 Μαΐου 2013 Η συνάρτηση θα δέχεται 4 παραμετρους ,καπως έτσι void func(float x, float y, float *rx, float * ry) { *rx= ... *ry= ... }
rafail1994 Δημοσ. 1 Μαΐου 2013 Μέλος Δημοσ. 1 Μαΐου 2013 Μάλιστα το ότι είναι void η συνάρτηση σε αυτήν την περίπτωση δεν υπάρχει πρόβλημα επειδή η "επιστροφή" γίνεται με τους pointers ε;
Star_Light Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 Μάλιστα το ότι είναι void η συνάρτηση σε αυτήν την περίπτωση δεν υπάρχει πρόβλημα επειδή η "επιστροφή" γίνεται με τους pointers ε; Η επιστροφη γινεται στο σημειο οπου έχεις καλεσει την συνάρτηση. Ο ελεγχος επιστρέφει εκει και ο δεικτης έχει κάνει τις αντιστοιχες αλλαγες στην μνήμη που βρισκεται η μεταβλητή. Μην μπερδεψεις αυτο με το οτι μια συνάρτηση μπορει πραγματικά να επιστρέψει έναν δείκτη και τοτε η φραση "η επιστροφη γινεται με τον δεικτη ή τους δεικτες" ειναι οντως 100% ακριβής. #include<stdio.h> int *double_number(int *); int main(void) { int x=2; printf(" Before : %d " , x); int *p = double_number (&x); printf(" After : %d , %d " , *p , x); return 0; } /* Το διπλασιο ενος αριθμου με την τροποποιηση μεσω δεικτη */ int *double_number(int *x) { *x=4; return x; }
rafail1994 Δημοσ. 2 Μαΐου 2013 Μέλος Δημοσ. 2 Μαΐου 2013 Αυτό το ότι η ("Η επιστροφη γινεται στο σημειο οπου έχεις καλεσει την συνάρτηση. Ο ελεγχος επιστρέφει εκει και ο δεικτης έχει κάνει τις αντιστοιχες αλλαγες στην μνήμη που βρισκεται η μεταβλητή.") το κατάλαβα . Αλλά και για να το ξεχωρίσω λίγο η διάφορα με το return στην συνάρτηση ποια είναι; Η πρώτη νομίζω ότι ότι δεν μπορείς να επιστρέψεις περισσότερες από μια μεταβλητές
παπι Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 H return επιστρεφει κατι, με το pass by pointer απλα γραφεις απανω σε μια θεση μνημης.
migf1 Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 Αυτό το ότι η ("Η επιστροφη γινεται στο σημειο οπου έχεις καλεσει την συνάρτηση. Ο ελεγχος επιστρέφει εκει και ο δεικτης έχει κάνει τις αντιστοιχες αλλαγες στην μνήμη που βρισκεται η μεταβλητή.") το κατάλαβα . Αλλά και για να το ξεχωρίσω λίγο η διάφορα με το return στην συνάρτηση ποια είναι; Η πρώτη νομίζω ότι ότι δεν μπορείς να επιστρέψεις περισσότερες από μια μεταβλητές Οι συναρτήσεις μπορούν να επιστρέψουν ένα μόνο "πράγμα", οπότε όταν εσύ θέλεις να επιστρέψεις περισσότερα του ενός έχεις διάφορες επιλογές. Μια λυση είναι να περνάς έξτρα ορίσματα στην συνάρτηση, ως διευθύνσεις (pointers) μεταβλητών για κάθε "πράγμα" που θέλεις να επιστρέψεις... το λεγόμενο "pass by reference" (δες κι εδώ: http://x-karagiannis.gr/prg/c-notes/pointers/usefulness/)... αυτό είναι που σου είπαν οι papi και albNik, δηλαδή τα έξτρα πράγματα που χρειάζεσαι τα "επιστρέφει" η συνάρτηση στις μεταβλητές rx και ry... και στην προκειμένη περίπτωση δεν χρησιμοποιείς καθόλου την τιμή επιστροφής της συνάρτησης αυτής κάθε αυτής (για αυτό και την ορίζεις ως void). Αν δεν σε ενδιέφερε να κρατήσεις τις αρχικές τιμές των ορισμάτων x και y, θα μπορούσες να περάσεις αυτά τα 2 μονάχα ως ορίσματα της συνάρτησης, αλλά "by reference" (ως δείκτες δηλαδή) και να υπολόγιζες απευθείας πάνω τους τις νέες τους τιμές. Όταν τελείωνε η συνάρτηση τα x και y θα είχαν χάσει τις αρχικές του τιμές και θα περιείχαν τις νέες που τους είχες αναθέσει μέσα στην συνάρτηση. Αργότερα όταν θα μάθετε και τα struct, θα μπορείς να "ομαδοποιείς" συναφή "πράγματα" ώστε να τα περνάς ή να τα επιστρέφεις ομαδοποιημένα προς και από τις συναρτήσεις (είτε ως ορίσματα, είτε ως επιστροφή των συναρτήσεων αυτών κάθε αυτών). Για παράδειγμα, αν είχες φτιάξει ένα struct Point που θα περιέχει την x και την y συντεταγμένη του σημείου που περιγράφει (αυτό που σου είπε δλδ ο παπι αρχικά), θα μπορούσες να γράψεις κάτι τέτοιο... struct Point { float x, y; }; ... struct Point func( float x, float y) { struct Point ret = { 0.0 ,0.0 }; /* start with ret.x=0.0, ret.y=0.0 */ ret.x = x + ... * ...; ret.y = y + ... * ...; return ret; } και στην main() σου κάτι τέτοιο... int main( void ) { float x = 2.00, y = 6.00; struct Point newPoint = func( x, y ); printf( "Before: x = %f, y = %f\n", x, y); printf( "After: x = %f, y = %f\n", newPoint.x, newPoint.y ); ... } Ή θα μπορούσες το struct να το περνάς by reference στην συνάρτηση, οπότε θα την όριζες ως void... void func( float x, float y, struct Point *newPoint ) { /* sanity check */ if ( NULL == newPoint ) return; /* do nothing, without crashing */ newPoint->x = x + ... * ...; newPoint->y = y + ... * ...; } και στην main() σου... int main( void ) { float x = 2.00, y = 6.00; struct Point newPoint = {0.0, 0.0}; /* start with newPoint.x=0.0, newPoint.y=0.0 */ func( x, y, &newPoint ); printf( "Before: x = %f, y = %f\n", x, y); printf( "After: x = %f, y = %f\n", newPoint.x, newPoint.y ); ... } Ή θα μπορούσες και τα x,y να τα βάλεις κι αυτά σε ένα struct Point (π.χ. struct Point oldPoint = {2.0, 6.0}; ) και να προσαρμόσεις ανάλογα και τον κώδικα της func() και της main(). Π.χ... struct Point func( struct Point oldPoint ) { oldPoint->x = ...; oldPoint->y = ...; return oldPoint; } ... int main( void ) { struct Point oldPoint = { 2.0, 6.0 }; struct Point newPoint = func( oldPoint ); printf( "Before: x = %f, y = %f\n", oldPoint.x, oldPoint.y); printf( "After: x = %f, y = %f\n", newPoint.x, newPoint.y ); ... } Γενικώς έχεις διάφορες επιλογές. [*] Όταν τα struct είναι πολύ μεγάλα τότε μας συμφέρει να τα διαχειριζόμαστε by reference προς και από τις συναρτήσεις, για να γλιτώνουμε χώρο (ίσως και χρόνο), Θα μπορούσαμε ακόμα και να δημιουργήσουμε δυναμικά το newPoint μέσα στην συνάρτηση func() και να επιστρέψουμε τη διεύθυνσή του στην main(), αλλά τότε θα έπρεπε να φροντίσουμε να απελευθερώσουμε στην main() και την μνήμη που είχε δεσμεύσει για αυτό το struct η func(), πριν τερματίσουμε το πρόγραμμά μας.
albNik Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 Βασικα δεν έχει νόημα να απελευθερώνεις μνημη αμέσως πριν τον τερματισμό του προγραμματος. 1
Star_Light Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 Αυτό το ότι η ("Η επιστροφη γινεται στο σημειο οπου έχεις καλεσει την συνάρτηση. Ο ελεγχος επιστρέφει εκει και ο δεικτης έχει κάνει τις αντιστοιχες αλλαγες στην μνήμη που βρισκεται η μεταβλητή.") το κατάλαβα . Αλλά και για να το ξεχωρίσω λίγο η διάφορα με το return στην συνάρτηση ποια είναι; Η πρώτη νομίζω ότι ότι δεν μπορείς να επιστρέψεις περισσότερες από μια μεταβλητές Βασικα δεν στο είπα σωστά με συγχωρεις ακριβώς μετα επιστρέφει ο ελεγχος απο την κλήση της συνάρτησης. Το return ειναι για να επιστρεφει μια τιμη αν η συνάρτηση έχει δηλωθει να έχει επιστρεφομενο τύπο αν ομως έχει δηλωθεί τύπου void τοτε δεν έχει επιστρεφομενο τύπο απλα επιστρέφει ο ελεγχος του προγραμματος χωρις να επιστρέψει η συνάρτηση τίποτα(καμια τιμή) και αν την βάλεις εσυ να επιστρεφει κάτι τοτε θα έχεις σφάλμα. Μπορεις φυσικα να χρησιμοποιησεις το keyword return χωρις κάποια τιμη σε αυτη την περίπτωση.Οταν η συνάρτηση ειναι να επιστρέψει ειτε μια τιμή τύπου int ειτε float ειτε οτιδηποτε τοτε δεν μπορεις παραπανω απο μια καθε φορα που καλεις την συνάρτηση. Καταλαβες ??? Οταν θα κανεις λιστες θα τα δεις καλυτερα ολα αυτα.
migf1 Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 Βασικα δεν έχει νόημα να απελευθερώνεις μνημη αμέσως πριν τον τερματισμό του προγραμματος. Ακόμα κι αν το πρόγραμμά σου τρέξει ως child process? Ιδιαίτερα σε κάποια "εξωτική" πλατφόρμα (π.χ. ενσωματωμένα συστήματα)? Είναι καλή πρακτική να κάνουμε free() την μνήμη που δεσμεύουμε δυναμικά πριν τερματίσουμε το πρόγραμμά μας (αμέσως ή οχι αμέσως πριν τον τερματισμό δεν έχει σημασία).
albNik Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 Οκ εννοούσα τερματισμό με την στενή έννοια. (Οτι θα φύγει από το task manager των windows)
cvb Δημοσ. 2 Μαΐου 2013 Δημοσ. 2 Μαΐου 2013 Καλησπέρα. Σχετικά με τη συζήτηση με το θέμα της μνήμης κάποιοι προγραμματιστές της Microsoft είχαν κάνει ένα λάθος σε κάποιο screensaver. Το default bitmap δεν γινόταν αντικατάσταση πάλι με αποτέλεσμα ο screensaver να τρέχει εκτός GDI πόρων. Σε περίπτωση που κάποιος ενδιαφέρεται για τα του GDI και Winapi τα εξηγεί εδώ http://www.winprog.org/tutorial/bitmaps.html στην παράγραφο GDI leaks.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα