Τα πάντα για την C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό stamatiou » 08 Σεπ 2011, 12:07

Οκ, σωστό είναι εκτός από εκείνο το return που μου ξέφυγε :oops: Αλλά τι θα πρέπει να επιστρέψει;
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 08 Σεπ 2011, 13:13

Star_Light έγραψε:...θελω να πω αυτο σιγουρα δεν ειναι υλη που διδασκεται σε αρχαριους εσυ τι λες?


Κανονικά αυτά θα έπρεπε να διδάσκονται όταν διδάσκονται οι δείκτες (δεν ξέρω σε ποιο έτος διδάσκονται, νομίζω το 1ο εφόσον μιλάμε για εξειδικευμένη σχολή πληροφορικής).

Πιο advanced είναι άλλα πράγματα, π.χ. η χρήση unions για να διαβάζεις και να τυπώνεις με συμβατό (portable) τρόπο τη διευθύνσεις δεικτών. Μη χαλαστείς αν δεν καταλάβεις τίποτα από το παρακάτω :lol: ... το δείχνω ως απλό δείγμα πιο προχωρημένων πραγμάτων (αν και το πρώτο μισό της main() θα πρέπει να είναι απόλυτα κατανοητό με τα όσα έχουμε πει μέχρι τώρα περί δεικτών).

Spoiler: show
Κώδικας: Επιλογή όλων

#include <stdio.h>

typedef struct ptraddresses {
union pp {
int **ptr;
unsigned long int address;
} pp;
union p {
int *ptr;
unsigned long int address;
} p;
} PtrAddresses;

// ---------------------------------------------------------------------
int main( void )
{
int n = 10, *p;
PtrAddresses portable = { {0UL}, {0UL} };

p = &n; //ή p = NULL; // αν το αφήσουμε μη-αρχικοποιημένο ρισκάρουμε seg-fault

// μη συμβατός τρόπος (implementation dependent, σύμφωνα με το C99 στάνταρ)

puts("NON_PORTABLE WAY(implentation defined)\n--------------------------------");
printf("memory address of p is : %lu\n", (unsigned long) &p );
printf("\tp points at address: %lu\n", (unsigned long) p );
if ( p != NULL )
{ // αν το p ΔΕΝ είναι αρχικοποημένο, το *p παράγει seg-fault
printf("\twhich contains the value: %d\n", *p);
}

putchar('\n');

// συμβατός τρόπος (δουλεύει εγγυημένα σε όλους τους compilers)

portable.pp.ptr = &p;
portable.p.ptr = p;

puts("PORTABLE WAY (works on all compilers)\n---------------------------------");
printf("memory address of p is : %lu\n", portable.pp.address );
printf("\tp points at address: %lu\n", portable.p.address );
if ( p != NULL )
{ // αν το p ΔΕΝ είναι αρχικοποημένο, το *(portable.p.ptr) παράγει seg-fault
printf("\twhich contains the value: %d\n", *(portable.p.ptr) );
}

putchar('\n');

return 0;
}
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 08 Σεπ 2011, 13:21

migf1 έγραψε:
......

Αν ελέγξουμε πρώτα το περιεχόμενο του δείκτη ( *src == '\0 ') τότε αν ο src είχε για παράδειγμα περαστεί με τιμή NULL στην συνάρτηση, έστω και κατά λάθος, τότε προκαλούμε segmentation-fault (και άρα κενό ασφαλείας) διότι NULL σημαίνει πως δείχνει στο ΠΟΥΘΕΝΑ (που στην πράξη σημαίνει πως δείχνει σε κάποιο τυχαίο σημείο της μνήμης ... undefined ). Οπότε, γράφοντας εμείς *src == '\0' ρισκάρουμε να μετατραπεί κάποια στιγμή στο run-time του προγράμματος σε *NULL == '\0'... κι εκεί αρχίζουν τα όργανα! :lol:

......



Eρωτήσεις :

1.Κάθε string της μορφής s1[]=""; ειναι κενό? Υπαρκτό μεν κενο δε... υπαρκτό επειδη φέρει τον μηδενικο χαρακτήρα ετσι?

2. Μπορεις να δώσεις ενα παράδειγμα απο ενα ανύπαρκτο string???

3. Εδω μπερδεύομαι λιγο γιατι ειχαμε πει πως σε απροσδιόριστη περιοχή δείχνουν μονο οι άκυροι δείκτες ενω ενας δείκτης ο οποίος δειχνει σε NULL δεν εχει μεν περιεχομενα αλλα ειναι έγκυρος.

4. Αν τα ορίσματα ήταν απλοί πίνακες (ωστε να εξασφαλίσουμε οτι καταρχην δεν θα μας άφηνε να δωσουμε NULL ουτε και κατα λαθος και επισης πως η ομαλή δέσμευση γίνεται αυτόματα) τοτε θα υπήρχε και διαφορά οταν θα τα βάζαμε σαν ορίσματα στην συνάρτηση??? θελω να πω δεν θα τα περνουσαμε ως δείκτες ετσι... αλλα παιζει να ειναι και περιττη αυτη η ερωτηση μιας και το λες και ο ιδιος οτι δεν θα τα διαχειριστουμε ως δεικτες.

5. Όταν δηλώνεις εναν δεικτη απλα πχ
Κώδικας: Επιλογή όλων
int *p;


περα απο το οτι δεν ειναι αρχικοποιημενος... δεν δεσμεύεται μνήμη για αυτον? Πρεπει αναγκαστικά να δωσεις calloc για να γινει έγκυρη αυτη η μνήμη? ΔΗλαδη ας πουμε αν ορισω εγω εναν δεικτη ουσιαστικα θα έχει απλα το προκαθορισμενο μέγεθος που είπαμε ειναι ιδιο για ολα τα data types χωρις αυτο να σημαινει πχ οτι τον έχω δεσμεύσει ωστε να μπορει να δείχνει για 10 θέσεις ας πουμε αν εγω πιο μετα σε ενα while τον αυξάνω με αριθμητικη δεικτων ε?

6. ΣΤο παρακατω απόσπασμα κώδικα

Κώδικας: Επιλογή όλων

if (src)
{
free(src);
src=NULL;
}


Το if(src) ειναι ισοδυναμο με το if(src!==NULL)
ενω το *src!=0 θα ίσχυες αν το string δεν ηταν κενό ?

Τέλος άν έχεις χρονο ριξε μια ματια και στους παραπανω κωδικες με spoiler που έβαλα ετσι μηπως εκανα καμια γκάφα αθελα μου ως προς λογικο λάθος. Thanx ;)
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 08 Σεπ 2011, 13:29

Star_Light έγραψε:Μια εξασκηση στα γρηγορα.....λιγο πριν παραθεσω αποριες

Spoiler: show
Κώδικας: Επιλογή όλων

#include<stdio.h>
#define INVALID -1
#define N 10

int main(void)
{
int x[N]={1,2,3,4,5,6,7,8,9,-1};
int *i;
i=x;

while(*i!=-1)
{
if(i==NULL)
printf("End");
else if(*i%2==0)
{
printf("\n ... ");
printf("\n%d",*i);
}
else if(*i%2==1)
{
printf("\n ... ");
printf("\n %d", *i);
}
i++;
}


return 0;
}


Το ...
Κώδικας: Επιλογή όλων

if ( i == NULL )
printf("End");

πρέπει να γίνει...
Κώδικας: Επιλογή όλων

if ( i == NULL )
puts("*** error, i does not point to usable data);
else {
while ...
}
...
return 0;

και να βγει έξω από το while.

Επίσης, γιατί ρε σεις επιμένετε να βάζετε άσχετα ονόματα στις μεταβλητές σας; Τα i,j,k τα χρησιμοποιούμε για μετρητές, τα x,y,z για πραγματικούς αριθμούς, τα l,m,n για ακέραιους, τα s,t,u για strings, τα p, ptr για δέικτες, τα pp, pptr για δείκτες σε δείκτες ... ξέρετε πόσο δύσκολο είναι να διαβαστεί από άλλους ο κώδικας που ποστάρετε; Τόσες φορές σας το έχω πει :(
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 08 Σεπ 2011, 13:36

stamatiou έγραψε:Οκ, σωστό είναι εκτός από εκείνο το return που μου ξέφυγε :oops: Αλλά τι θα πρέπει να επιστρέψει;

Το αντιγραμμένο dst ή NULL σε περίπτωση σφάλματος (και δεν είναι σωστό, πχ τι κάνει όταν dst[100]="" και src[19] = "1234" ?).
Τελευταία επεξεργασία από migf1 και 08 Σεπ 2011, 13:43, έχει επεξεργασθεί 2 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 08 Σεπ 2011, 13:38

migf1 έγραψε:
Star_Light έγραψε:Μια εξασκηση στα γρηγορα.....λιγο πριν παραθεσω αποριες

Spoiler: show
Κώδικας: Επιλογή όλων

#include<stdio.h>
#define INVALID -1
#define N 10

int main(void)
{
int x[N]={1,2,3,4,5,6,7,8,9,-1};
int *i;
i=x;

while(*i!=-1)
{
if(i==NULL)
printf("End");
else if(*i%2==0)
{
printf("\n ... ");
printf("\n%d",*i);
}
else if(*i%2==1)
{
printf("\n ... ");
printf("\n %d", *i);
}
i++;
}


return 0;
}


Το ...
Κώδικας: Επιλογή όλων

if ( i == NULL )
printf("End");

πρέπει να γίνει...
Κώδικας: Επιλογή όλων

if ( i == NULL )
puts("*** error, i does not point to usable data);
else {
while ...
}
...
return 0;

και να βγει έξω από το while.

Επίσης, γιατί ρε σεις επιμένετε να βάζετε άσχετα ονόματα στις μεταβλητές σας; Τα i,j,k τα χρησιμοποιούμε για μετρητές, τα x,y,z για πραγματικούς αριθμούς, τα l,m,n για ακέραιους, τα s,t,u για strings, τα p, ptr για δέικτες, τα pp, pptr για δείκτες σε δείκτες ... ξέρετε πόσο δύσκολο είναι να διαβαστεί από άλλους ο κώδικας που ποστάρετε; Τόσες φορές σας το έχω πει :(


Ε βασικα δεν τον προσεξα επειδη τον εκανα στα γρηγορα.... :/

Μια φορα θα γινει ο έλεγχος για NULL? Και αρκει?
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 08 Σεπ 2011, 13:41

(μισό ένα-ένα :lol: ... διαβάζω τώρα το post σου με τις πολλές ερωτήσεις για να τις απαντήσω :) )
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 08 Σεπ 2011, 13:43

migf1 έγραψε:(μισό ένα-ένα :lol: ... διαβάζω τώρα το post σου με τις πολλές ερωτήσεις για να τις απαντήσω :) )


χαχαχαχ ναι εχεις δικιο ψιλο αγχωθηκα και σε πηρα μονοτερμα.
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 08 Σεπ 2011, 14:51

Πετάχτηκα μέχρι την τράπεζα, λοιπόν...

Star_Light έγραψε:
migf1 έγραψε:
......

Αν ελέγξουμε πρώτα το περιεχόμενο του δείκτη ( *src == '\0 ') τότε αν ο src είχε για παράδειγμα περαστεί με τιμή NULL στην συνάρτηση, έστω και κατά λάθος, τότε προκαλούμε segmentation-fault (και άρα κενό ασφαλείας) διότι NULL σημαίνει πως δείχνει στο ΠΟΥΘΕΝΑ (που στην πράξη σημαίνει πως δείχνει σε κάποιο τυχαίο σημείο της μνήμης ... undefined ). Οπότε, γράφοντας εμείς *src == '\0' ρισκάρουμε να μετατραπεί κάποια στιγμή στο run-time του προγράμματος σε *NULL == '\0'... κι εκεί αρχίζουν τα όργανα! :lol:

......



Eρωτήσεις :

1.Κάθε string της μορφής s1[]=""; ειναι κενό? Υπαρκτό μεν κενο δε... υπαρκτό επειδη φέρει τον μηδενικο χαρακτήρα ετσι?

Υπαρκτό επειδή έχει δεσμευτεί έγκυρη μνήμη για αυτό (αυτόματα, λόγω το ορισμού του με σύνταξη πινάκων :) ) Επίσης, ναι μπορούμε να το θεωρήσουμε ως κενό string επειδή ο 1ος του χαρακτήρας είναι ο μηδενικός (με γενική ορολογία πινάκων όμως δεν είναι κενό, έχει ένα στοιχείο στη 1η του θέση, τον μηδενικό χαρακτήρα).

έγραψε:2. Μπορεις να δώσεις ενα παράδειγμα απο ενα ανύπαρκτο string???

Κώδικας: Επιλογή όλων

char *string = NULL; // έγκυρο αλλά ανύπαρκτο γιατί δεν έχει δείχνει σε υπαρκτά περιεχόμενα, δεν έχει καν περιεχόμενα
char *string; // υπαρκτό αλλά άκυρο, γιατί δείχνει άκυρα περιεχόμενα (περιεχόμενα για τα οποία δεν έχουμε την παραμικρή ιδέα ποια είναι και που βρίσκονται)
char *string = calloc(100, sizeof(char) ); // υπαρκτό κι έγκυρο, με τα περιεχόμενά του να αποτελούνται από 100 μηδενικούς χαρακτήρες


έγραψε:3. Εδω μπερδεύομαι λιγο γιατι ειχαμε πει πως σε απροσδιόριστη περιοχή δείχνουν μονο οι άκυροι δείκτες ενω ενας δείκτης ο οποίος δειχνει σε NULL δεν εχει μεν περιεχομενα αλλα ειναι έγκυρος.

Η διατύπωση που είχα κάνει στο κομμάτι που παραθέτεις ήταν πριν σας μιλήσω για άκυρους κι έγκυρους δείκτες, ελπίζοντας πως θα σας βοηθούσε χωρίς να χρειαστεί να πάμε σε περισσότερο βάθος. Εφόσον πήγαμε πιο βαθιά όμως, κρατήστε τη τελευταία διατύπωση που εισαγάγει και τους όρους "άκυρος" και "έγκυρος".

Το καλύτερο από όλα είναι να κρατήσετε πως όταν ορίζετε δείκτες πρέπει να τους αρχικοποιείτε άμεσα (με calloc() ή σε NULL) και να ελέγχετε αν είναι NULL πριν τους απελευθερώσετε με free() κι αμέσως μετά να τους αναθέτετε την τιμή NULL.

έγραψε:4. Αν τα ορίσματα ήταν απλοί πίνακες (ωστε να εξασφαλίσουμε οτι καταρχην δεν θα μας άφηνε να δωσουμε NULL ουτε και κατα λαθος και επισης πως η ομαλή δέσμευση γίνεται αυτόματα) τοτε θα υπήρχε και διαφορά οταν θα τα βάζαμε σαν ορίσματα στην συνάρτηση??? θελω να πω δεν θα τα περνουσαμε ως δείκτες ετσι... αλλα παιζει να ειναι και περιττη αυτη η ερωτηση μιας και το λες και ο ιδιος οτι δεν θα τα διαχειριστουμε ως δεικτες.

Μπορούμε να τα περάσουμε και ως δείκτες, δεν υπάρχει πρόβλημα.

έγραψε:
5. Όταν δηλώνεις εναν δεικτη απλα πχ
Κώδικας: Επιλογή όλων
int *p;


περα απο το οτι δεν ειναι αρχικοποιημενος... δεν δεσμεύεται μνήμη για αυτον? Πρεπει αναγκαστικά να δωσεις calloc για να γινει έγκυρη αυτη η μνήμη? ΔΗλαδη ας πουμε αν ορισω εγω εναν δεικτη ουσιαστικα θα έχει απλα το προκαθορισμενο μέγεθος που είπαμε ειναι ιδιο για ολα τα data types χωρις αυτο να σημαινει πχ οτι τον έχω δεσμεύσει ωστε να μπορει να δείχνει για 10 θέσεις ας πουμε αν εγω πιο μετα σε ενα while τον αυξάνω με αριθμητικη δεικτων ε?

Ακριβώς!

έγραψε:6. ΣΤο παρακατω απόσπασμα κώδικα

Κώδικας: Επιλογή όλων

if (src)
{
free(src);
src=NULL;
}


Το if(src) ειναι ισοδυναμο με το if(src!==NULL)
ενω το *src!=0 θα ίσχυες αν το string δεν ηταν κενό ?

To if ( src ) εξασφαλίζει πως ο src έχει κάποια περιεχόμενα (δεν είναι NULL δηλαδή)... και άρα μπορείς κατόπιν να ελέγξεις αυτά τα περιεχόμενα, που ξεκινάνε με *src. Το να είναι έγκυρα όμως αυτά τα περιεχόμενα πρέπει να το έχεις εξασφαλίσει εσύ πριν φτάσεις στο if ( src ).

Η οποιαδήποτε ενέργεια που εμπλέκει το *src πρέπει να είναι πάντα είναι το επόμενο στάδιο μετά το if ( src ) και ποτέ προηγούμενο.

Ο όρος "κενό" για το περιεχόμενο του src είναι σχετικός, όπως εξήγησα παραπάνω στην απάντηση Νο.1
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 08 Σεπ 2011, 14:57

Οκ . Είμαστε πλήρεις. Να κανω τωρα μια πιο άσχετη αλλα και συνάμα προσωπικη ερώτηση.
Σιγουρα το να ειναι μεταδοτικος κάποιος ειναι χάρισμα... αλλα περαν του οτι εισαι μεταδοτικός ολα αυτα τα ειχες διδαχθεί ετσι? Θελω να πω με τον τροπο που τα εξηγεις...
Γιατι σε εμας που εκαναν την C απο οσο θυμαμαι ηταν πολυ αρτσι μπουρτσι και λουλας. Πραγματικα αν ειχα τα μυαλα που εχω τωρα ουτε πανελληνιες ουτε τιποτα με την μια εξωτερικο για σπουδες.... θα ειχα φυλαξει τα λεφτα απο τα φροντιστηρια σε ολο το λυκειο
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι