Star_Light Δημοσ. 9 Δεκεμβρίου 2012 Δημοσ. 9 Δεκεμβρίου 2012 (επεξεργασμένο) Αν δεν υπάρχει το 10, τότε ο πίνακας str1 θα οριστεί με μέγεθος όσο χρειάζεται για το literal δηλαδή 5 + 1 οπότε η strcat θα έγραφε πάνω σε μνήμη που δεν την ανήκει ή θα βαρούσε segmentation fault. Υπό ποιες "κανονικές" συνθήκες υπολογίζει ο compiler το μέγεθος αυτόματα ? Ok. Eυχαριστω Kανονικες συνθηκες εννοουσα τον initializer που προσθέτει τον μηδενικο στο τελος. Οτι ακριβως παιζει και με τα απλα arrays δηλαδη..... με αλλα λογια αναρωτηθηκα αν ενω παραλειψουμε το μεγεθος και μετα την κλήση της strcat ο μεταγλωτιστής θα μεριμνησει ωστε να βρει το μέγεθος του πινακα για την προσάρτηση του string. Αυτο ρωτησα Γιατι το λες literal ομως? Δεν ειναι string literal . > #include<stdio.h> #include<string.h> int main( void ) { char *p="message"; // string literal char str[]="message"; str[1]='m'; printf("%s" , str); p[1]='m'; // SEGM FAULT printf("%s" , p); return 0; } Επεξ/σία 9 Δεκεμβρίου 2012 από Star_Light
imitheos Δημοσ. 9 Δεκεμβρίου 2012 Δημοσ. 9 Δεκεμβρίου 2012 με αλλα λογια αναρωτηθηκα αν ενω παραλειψουμε το μεγεθος και μετα την κλήση της strcat ο μεταγλωτιστής θα μεριμνησει ωστε να βρει το μέγεθος του πινακα για την προσάρτηση του string. Αυτο ρωτησα Ο προγραμματιστής πρέπει να φροντίσει η παράμετρος "dest" της strcat να έχει αρκετό χώρο. Ο compiler δεν μεριμνά για κανένα μέγεθος. > #include<stdio.h> #include<string.h> int main( void ) { char str1[]="Hello"; int i = 5; char str2[]="Dude"; printf("i = %d\n",i); printf("%s\n" , strcat(str1,str2)); // HelloDude printf("i = %d\n",i); return 0; } Έξοδος: i = 5 HelloDude i = 5 #include<stdio.h> #include<string.h> int main( void ) { char str1[]="Hello"; int i = 5; char str2[]="DudeDude"; printf("i = %d\n",i); printf("%s\n" , strcat(str1,str2)); // HelloDude printf("i = %d\n",i); return 0; } Έξοδος: i = 5 HelloDudeDude i = 101 Με άλλα λόγια, το πρόγραμμα που είχες δώσει φαινομενικά έπαιζε σωστά γιατί ο compiler δέσμευε παραπάνω μνήμη από ότι έπρεπε και έτσι δεν φαινόταν το overwrite. Όταν το Dude έγινε DudeDude, η strcat έγραψε και στην περιοχή που είναι το i. Για να δούμε τι εννοείς, γράψε ένα πρόγραμμα που καλεί την strcat και που σύμφωνα με το σκεπτικό σου ο compiler μεριμνά ώστε να βρει το μέγεθος του πίνακα.
Star_Light Δημοσ. 9 Δεκεμβρίου 2012 Δημοσ. 9 Δεκεμβρίου 2012 Ο compiler σε μια δήλωση > char str1[] = "Hello"; Θα υπολογίσει το μέγεθος αν εμεις το παραλειψουμε , το μεριμνάω μπορει να μην ειναι το καταλληλο ρήμα ενταξει. Απλα εγω αναρωτηθηκα αν και στην περιπτωση με την strcat θα κανει το ιδιο αλλα αυτο τωρα που το ξανασκεφτομαι ειναι τελειως λαθος γιατι ουτως ή αλλως σε δηλωσεις αυτης της μορφης ο compiler υπολογιζει το μέγιστο μήκος του πινακα και απο εκει και επειτα αυτο ειναι fixed (στην προκειμενη ειναι 6 φυσικα λογω των 5 + ο null character)! Οσες φορες και αν μεταγλωτιστει.... Για αυτο αν ειδες στον αρχικο κωδικα που έδωσα και χρησιμοποιω μεσα την strcat βαζω απο μονος μου το 10 μέσα στον str1. υ.γ Στην strcpy οταν λεει οτι το str2 δεν θα πρεπει να ειναι n-1 χαρακτηρες μεγαλυτερο απο το str1 μήκους n εννοει μαζι με τον μηδενικό ετσι? (στο str1 δηλαδη το μήκος n έχει μεσα και τον μηδενικο).
migf1 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 ... υ.γ Στην strcpy οταν λεει οτι το str2 δεν θα πρεπει να ειναι n-1 χαρακτηρες μεγαλυτερο απο το str1 μήκους n εννοει μαζι με τον μηδενικό ετσι? (στο str1 δηλαδη το μήκος n έχει μεσα και τον μηδενικο). Ποιος και που το λέει αυτό; Ρωτάω γιατί αφενός δεν βρίσκω κάτι τέτοιο στον ορισμό των strcpy και strncpy, και αφετέρου δεν καταλαβαίνω πως γίνεται κάτι που μιλάει για strcpy() να αναφέρεται σε ένα ξεκάρφωτο n.
Star_Light Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Ποιος και που το λέει αυτό; Ρωτάω γιατί αφενός δεν βρίσκω κάτι τέτοιο στον ορισμό των strcpy και strncpy, και αφετέρου δεν καταλαβαίνω πως γίνεται κάτι που μιλάει για strcpy() να αναφέρεται σε ένα ξεκάρφωτο n. Στον King το ειδα... σελ 290. Κοιτα αυτο που ρωταω ειναι τι γινεται στην περιπτωση που έχουν ακριβως ιδιο τρέχον μήκος n Ιn the call strcpy(str1 , str2) , strcpy has no way to check that the string pointed to by str2 will actually fit in the array pointed to by str1. Suppose that str1 points to an array of length n. If the string that str2 points to has no more than n-1 characters , then the copy will succeed . But if str2 points to a longer string , undefined behaviour occurs (Since strcpy always copies up to the first null character ,it will continue copying past the end of the array that str1 points to.) Aρχικα ο King λέει οτι άν πχ έχεις > char str1[]="hi"; char str2[]="my"; Τοτε η strcpy θα αντιγράψει και τον null character απο το str2 στο str1. Δηλαδη my'\0' στο hi\'0' O Κing πιο κατω λεει οτι άν το str2 έχει παραπάνω απο n-1 (που προφανως εδω εχει μιας και ειναι n μήκους και αυτο) η συμπεριφορα ειναι απροσδιοριστη (αν δειχνει σε μεγαλυτερο). Γιατι λέει για παραπανω απο n-1 και οχι n . n-1 εννοει μονο τους ωφέλιμους? Βασικα αυτο θα εννοει. Δεν ξερω αν μονο σε μενα φαινεται λιγο περιεργη η διατυπωση.
migf1 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Μπορείς πανεύκολα να δεις τι γίνεται γράφοντας 2-3 γραμμές κώδικα μόνος σου. Σε γενικές γραμμές το 'length' αναφέρεται στο strlen() και το 'size' στο sizeof() ... δεν ξέρω πως τα εννοεί ο King παραπάνω, άλλα όπως σου είπα, γράψε 2-3 γραμμές κώδικά και τεστάρισέ το να δεις πως συμπεριφέρεται στην κάθε περίπτωση.
imitheos Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Μια χαρά τα λέει ο King. "n-1 characters" οπότε χωρίς το \0.
nik324 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 > struct a{ int v1; int v2; }; struct a ** array; int size = 10; int main(){ array = (struct a **)malloc( sizeof(struct a *) * size ); return 0; } Υπάρχει κάτι παραπάνω που κάνω λάθος?? Γιατι αν παω να τυπώσω τη θέση 100 του πίνακα μου την τυπώνει κανονικά ενώ έχει 10 στοιχεία???
defacer Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Υπάρχει κάτι παραπάνω που κάνω λάθος?? Γιατι αν παω να τυπώσω τη θέση 100 του πίνακα μου την τυπώνει κανονικά ενώ έχει 10 στοιχεία??? Ένα λάθος είναι ότι κάνεις cast την επιστρεφόμενη τιμή της malloc, αλλά δεν έχει καμία σχέση με την απορία σου (είναι λάθος μόνο και μόνο επειδή αφήνει ανοιχτή την πόρτα για bug το οποίο χωρίς το cast δε θα μπορούσε να υπάρξει). Κατά τα άλλα δε μας δείχνεις τι πας να κάνεις με τον πίνακα, αλλά είναι λίγο δύσκολο να φανταστώ τι εννοείς ότι την τυπώνει "κανονικά". Σίγουρα αυτό που συμβαίνει δεν είναι "κανονικό", όπως κανονικό δεν είναι και αυτό το οποίο όμως τρέχει: > function test() { int x; char y[10]; int z; printf("%d", y[11]); } Ο λόγος είναι πως το y[11] παραπάνω o compiler το βλέπει ως >y + 11 το οποίο υπολογίζεται ως >&y + 11 * sizeof(y[0]) Αυτό γενικά δείχνει σε κάποια διεύθυνση μνήμης. Αν η διεύθυνση είναι έγκυρη και έχεις πρόσβαση σ' αυτή, θα δεις τα περιεχόμενά της. Το γεγονός ότι είναι εκτός του πίνακα y όπως τον έχεις ορίσει δεν παίζει ρόλο (στη C).
Star_Light Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Μπορείς πανεύκολα να δεις τι γίνεται γράφοντας 2-3 γραμμές κώδικα μόνος σου. Σε γενικές γραμμές το 'length' αναφέρεται στο strlen() και το 'size' στο sizeof() ... δεν ξέρω πως τα εννοεί ο King παραπάνω, άλλα όπως σου είπα, γράψε 2-3 γραμμές κώδικά και τεστάρισέ το να δεις πως συμπεριφέρεται στην κάθε περίπτωση. To δοκιμασα ρε συ. Αλλα μου το βγαζει κανονικα... > #include<stdio.h> #include<string.h> int main( void ) { char str1[]="hello"; char str2[]="hellom"; strcpy(str1,str2); puts(str1); return 0; } OUTPUT: > hellom Κατα τύχη δουλευει. Για αυτο και δεν μπορεσα να εχω ξεκαθαρη εικονα. @ημιθεε οκ.
nik324 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Ένα λάθος είναι ότι κάνεις cast την επιστρεφόμενη τιμή της malloc, αλλά δεν έχει καμία σχέση με την απορία σου (είναι λάθος μόνο και μόνο επειδή αφήνει ανοιχτή την πόρτα για bug το οποίο χωρίς το cast δε θα μπορούσε να υπάρξει). Κατά τα άλλα δε μας δείχνεις τι πας να κάνεις με τον πίνακα, αλλά είναι λίγο δύσκολο να φανταστώ τι εννοείς ότι την τυπώνει "κανονικά". Σίγουρα αυτό που συμβαίνει δεν είναι "κανονικό", όπως κανονικό δεν είναι και αυτό το οποίο όμως τρέχει: > function test() { int x; char y[10]; int z; printf("%d", y[11]); } και γιατι τρεχει αφου δεν ειναι κανονικο?? Aυτο που θέλω να κάνω είναι να έχω ένα πίνακα array[] ο οποιος να δειχνει σε NULL και να ειναι ετοιμος να δειξει σε στοιχεια τύπου struct a Αλλα παρατηρησα οτι κατι δεν παει καλά και συνεχιζω να μην καταλαβαίνω τι γινετε
defacer Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 και γιατι τρεχει αφου δεν ειναι κανονικο?? Για να μάθεις να προγραμματίζεις σε C. Κατά τα άλλα θα πρέπει να κάνεις memset() τον πίνακα αμέσως μετά τη malloc() (για να αρχικοποιήσεις όλα τα στοιχεία του σε 0). Απο κει και πέρα το "κάτι δεν πάει καλά" δεν είναι ιδιαίτερα κατατοπιστικό, ιδιαίτερα εφόσον αναφέρεται σε κώδικα που δεν έδειξες.
nik324 Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Για να μάθεις να προγραμματίζεις σε C. Κατά τα άλλα θα πρέπει να κάνεις memset() τον πίνακα αμέσως μετά τη malloc() (για να αρχικοποιήσεις όλα τα στοιχεία του σε 0). Απο κει και πέρα το "κάτι δεν πάει καλά" δεν είναι ιδιαίτερα κατατοπιστικό, ιδιαίτερα εφόσον αναφέρεται σε κώδικα που δεν έδειξες. Συνεχίζω να μην καταλαβαίνω τι γίνετε....κατι δεν πάει καλά μάλλον με μένα... Aυτο που εστειλα ειναι το πρόβλημα μου...δεν είναι κατι άλλο σε αλλο κώδικα Πως γινετε να μου τυπώνει στοιχειο του πίνακα που δεν υπάρχει????
imitheos Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 Συνεχίζω να μην καταλαβαίνω τι γίνετε....κατι δεν πάει καλά μάλλον με μένα... Aυτο που εστειλα ειναι το πρόβλημα μου...δεν είναι κατι άλλο σε αλλο κώδικα Πως γινετε να μου τυπώνει στοιχειο του πίνακα που δεν υπάρχει???? Σου απάντησε ο defacer πως γίνεται. Την C δεν τη νοιάζει πόσα στοιχεία έχει ο πίνακάς σου (ή ακόμη και αν είναι πίνακας ή τον μεταχειρίζεσαι εσύ σαν πίνακα). Ας πάρουμε το απλό σενάριο που έχουμε ένα πίνακα ακεραίων (πχ int k[10]) και ότι ο τύπος int έχει μέγεθος 4. Όταν εσύ δήλωσες τον πίνακα δεσμεύτηκε για αυτόν μια περιοχή μνήμης και από εκεί και πέρα είναι γνωστό ότι η μεταβλητή k αντιστοιχεί στην διεύθυνση Χ. Όταν εσύ πας να προσπελάσεις το 4ο στοιχείο και γράφεις k[3] = 5, η διαδικασία που γίνεται είναι να παίρνει την διεύθυνση X που αντιστοιχεί στο 1ο στοιχείο και να προσθέτει 3 φορές 4 bytes που καταλαμβάνει ο κάθε ακέραιος. Έτσι δηλαδή προσπελαύνεις την διεύθυνση X+12. Αν γράψεις k[30] = 5, θα πάει και θα γράψει στην διεύθυνση X+120 χωρίς να νοιάζεται που αυτή η διεύθυνση είναι εκτός του πίνακά σου. Αν αυτή η περιοχή μνήμης ανήκει στο πρόγραμμά σου και έχεις δικαιώματα εγγραφής, θα γράψει εκεί κανονικά σβήνοντας ότι υπάρχει εκεί που μπορεί να είναι σημαντικό. Αν δεν έχεις δικαιώματα εγγραφής, θα βαρέσει segmentation fault.
Directx Δημοσ. 10 Δεκεμβρίου 2012 Δημοσ. 10 Δεκεμβρίου 2012 [..]Πως γινετε να μου τυπώνει στοιχειο του πίνακα που δεν υπάρχει???? Γίνεται διότι όταν κάνεις malloc δεσμεύεις ένα τυχαίο μπλοκ μνήμης - το περιεχόμενο του μπορεί να περιέχει οποιαδήποτε τιμή (σκουπίδια), αν θες υποχρεωτικά να πάρεις ένα καθαρό μπλοκ δίχως memset κλπ χρησιμοποίησε την calloc αντί της malloc που μηδενίζει το μπλοκ που σου επιστρέφει. * Οπ! Αν ρωτάς πως γίνεται να γράφεις σε θέση του πίνακα που δεν έχεις δεσμεύσει ο φίλος imitheos στα εξηγεί αναλυτικά!
Προτεινόμενες αναρτήσεις