Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπερα σας ! Εχω μια ερωτιση. Αρχισα μαθηματα C++ απο ενα Αγγλικο site. Εχω μια ερωτηση. ΤΟ googlαρα αλλα και παλι δεν καταλαβα. ΤΙ ειναι η Variable Declaration. Εχω κολλησει και δεν καταλαβαινω τιποτα απο οτι μου γραφουν εκει μεσα.

Δημοσ.

Declaration είναι αυτά:

extern int age; // variable declaration
void func(); // function declaration
class Person; // class forward declaration

Έτσι λες στον compiler τι είδους πράγμα είναι το age, το func και το Person ούτως ώστε όταν αργότερα τα συναντήσει μπροστά του να μη σε σταματήσει με error "επ, τι είναι αυτό εδώ?". Δεν του ορίζεις όμως τι είναι -- για παράδειγμα, OK, η func είναι μια συνάρτηση αλλά τι ακριβώς κάνει; Η Person είναι μια class αλλά τι ακριβώς class; Δεν δίνεις δηλαδή τον ορισμό (definition).

 

Αυτός είναι ο λόγος που αν γράψεις π.χ.

class Person;
Person* p;

δεν υπάρχει πρόβλημα -- ο compiler ξέρει πως το p είναι pointer, δεν ξέρει σε τι κάνει point ακριβώς αλλά δεν τον νοιάζει κιόλας (δε χρειάζεται το definition). Αν όμως γράψεις αυτό:

class Person;
Person p;

τότε θα πάρεις error γιατί "μου είπες να σου φτιάξω ένα Person αλλά δε μου είπες τι είναι το Person ακριβώς"¨.

 

To definition λοιπόν είναι εκεί που ορίζεις τι ακριβώς είναι το όνομα στο οποίο αναφέρεσαι. Τις περισσότερες φορές (αλλά όχι απαραίτητα) declaration και definition δίνονται μαζί:

int age = 22;
void foo() { printf("Hello world"); }

Δες αν θες: http://stackoverflow.com/q/1410563/50079

  • Like 3
Δημοσ.

Επίσης, αν θες να χρησιμοποιήσεις έναν πίνακα 5 θέσεων,

στο declaration μπορείς απλά να γράψεις αυτό:

extern int a[];

Κάπου αλλού θα τον κάνεις define:

int a[5];
Δημοσ.

Μαλιστα. Δηλαδη αυτο ειναι κατι ΜΟΝΟ για τον μεταγλωττιστη(οχι για τον χρηστη) και ουσιαστηκα, δινεις στον μεταγλωττιστη, μια "λιστα" με τα types και τα ονοματα, χωρις ομως να του λες τι κανει, η τι θα κανει, το καθενα απο αυτα. Σωστα ??

Δημοσ.

Βασικα εχεις στο αρχειο first.c int a=5; //definition

και θες να χρησιμοποιησεις το a απο το αρχειο second.c

Στο second.c πρεπει πρωτα να κανεις declare οτι το a υπαρχει (extern int a;) και ο linker θα ψαξει μεχρι να το βρει στο first.c.

Δημοσ.

Από τη δική μου οπτική γωνία είναι ένα feature που προσφέρει ο μεταγλωττιστής

για να γράψουμε πιο modularized κώδικα. Θα μπορούσε να μας αναγκάζει να κά-

νουμε δηλώσεις/ορισμούς σε μία γραμμή όπως προειπώθηκε. Όπως και να έχει,

δήλωση και ορισμός είναι από τα "αηδιαστικά" βασικά πράγματα που κάνει ένας

μεταγλωττιστής και είναι έννοιες που συνδέονται άμεσα με τον πίνακα συμβόλων.

Μία δομή, η οποία κρατά πληροφορία για τα δηλωμένα και ορισμένα σύμβολα κ.α.

 

Όταν ορίζεις μία μεταβλητή δύο φορές στο ίδιο scope ή όταν χρησιμοποιείς μία με-

ταβλητή που δεν είναι δηλωμένη/ορισμένη, τότε αυτό εντοπίζεται, αφού γίνει κάποιου

είδους αναζήτηση στον πίνακα συμβόλων.

Δημοσ.

Μαλιστα. Νομιζω οτι καταλαβα. ουσιαστηκα πολυ απλα... δηλωνεις την μεταβλητη ως τι τυπος ειναι. ΠΧ γραφω στην αρχη:

 

extern int F;

 

και μετα απο πολλες γραμμες  κωδικα ΠΧ:

 

int main ()

{

F = 9;

 

κ.τ.λ

}

 

Ουσιαστηκα φτιαχνω απο πιο πριν, μια λιστα για το τι ΘΑ χρεισημοποιησω. Νομιζω οτι καταλαβα. Και μια ερωτιση:Αντι να το κανουμε απο πιο πριν, αν το κανουμε στην ιδια γραμμη, τι προβληματα μπορει να δημιουργησει ??

Δημοσ. (επεξεργασμένο)

Μαλιστα. Νομιζω οτι καταλαβα. ουσιαστηκα πολυ απλα... δηλωνεις την μεταβλητη ως τι τυπος ειναι. ΠΧ γραφω στην αρχη:

 

extern int F;

 

και μετα απο πολλες γραμμες  κωδικα ΠΧ:

 

int main ()

{

F = 9;

 

κ.τ.λ

}

 

Ουσιαστηκα φτιαχνω απο πιο πριν, μια λιστα για το τι ΘΑ χρεισημοποιησω. Νομιζω οτι καταλαβα. Και μια ερωτιση:Αντι να το κανουμε απο πιο πριν, αν το κανουμε στην ιδια γραμμη, τι προβληματα μπορει να δημιουργησει ??

Πρέπει να την ορίσεις κιόλας. Οπότε μέσα στη main, γράφεις int F = 9;.

 

Συνήθως δηλώνουμε global external μεταβλητές σε header files.

Επεξ/σία από gon1332
Δημοσ.

Πρέπει να την ορίσεις κιόλας. Οπότε μέσα στη main, γράφεις int F = 9;.

Το μπερδευεις ετσι.

τωρα εχεις δυο διαφορετικες μεταβλητές.

Στην main ειναι local. Οι local variables δεν μπορει να ειναι και extern.

  • Like 1
Δημοσ.

Το μπερδευεις ετσι.

τωρα εχεις δυο διαφορετικες μεταβλητές.

Στην main ειναι local. Οι local variables δεν μπορει να ειναι και extern.

Oops, my bad. Corrected.

Δημοσ.

@ts:

 

Έστω ότι ορίζεις 2 συναρτήσεις a και b:

 

void a( void )
{
    b();
}

void b( void )
{
    ...
}
Ο κομπάιλερ θα χτυπήσει έρρορ στον ορσιμό της a, επειδή δεν ξέρει τι είναι το b().

 

Μια λύση είναι να ορίσεις την b πριν την a:

void b( void )
{
    ...
}
void a( void )
{
    b();
}
Μια άλλη λύση είναι να διατηρήσεις τον αρχικό κώδικα, αλλά να δηλώσεις την b() πριν την χρησιμοποιήσεις (και πριν την ορίσεις):

void b( void );  // declaration

void a( void )
{
    b();
}

// definition
void b( void )
{
    ...
}
Αν δεν με απατάει η μνήμη μου, θα μπορούσες εναλλακτικά να δηλώσεις την b() μέσα στην a():

void a( void )
{
    void b( void); // declaration
    b();
}
void b( void )
{
    ...
}
αλλά τσέκαρέ το στον compiler σου αυτό το τελευταίο γιατί δεν είμαι 100% σίγουρος.

 

Ο ορισμός της b() δεν χρειάζεται να είναι στο ίδιο αρχείο με τον ορισμό της a(). Θα μπορούσε ας πούμε να ορίζεται σε ένα αρχείo b.c, και η δήλωση της με το extern keyword να βρίσκεται σε ένα αρχείο b.h Με αυτό το παράδειγμα, σε όποιο αρχείο θες να χρησιμοποιήσεις την b() κάνεις #include "b.h" και προφανώς στον compiler προσθέτεις και το b.c αρχείο.

 

Οι μεταβλητές λειτουργούν με παραπλήσια λογική, αλλά όχι ακριβώς γιατί εκείνες έχουν πιο σύνθετο scope από τις συναρτήσεις. Π.χ. μπορεί να είναι internally global, externally global, ή local σε κάποια συνάρτηση. Ενώ οι συναρτήσεις δεν μπορούν να έχουν local scope μέσα σε άλλη συνάρτηση, γιατί η γλώσσα δεν επιτρέπει nested functions. Έχουν είτε intenal είτε external linkage, το οποίο σε γενικές γραμμές μεταφράζεται σε file scope (βασικά σε source module scope ή αλλιώς σε compilation unit scope);

 

Οπότε, στο παράδειγμα που έδωσες:

extern int F;
...
int main( void )
{
    F = 9;
}
ο κώδικας θα δουλέψει αν το F το έχεις ορίσει σε κάποιο άλλο αρχείο, το οποίο το έχεις συμπεριλάβει στο compilation. Έτσι σκέτο όπως το έχεις όμως δεν θα δουλέψει, γιατί το F δεν το ορίζεις πουθενά.

Αν κάνεις αυτό που είπε από λάθος ο gon:

extern int F;
...
int main( void )
{
    int F;
    F = 9;
    ...
}
τότε όπως πολύ σωστά παρατήρησε ο albnik, έχεις 2 μεταβλητές. Μια καθολική F με external linkage την οποία την έχεις μεν δηλώσει αλλά δεν δείχνεις που την έχεις ορίσει (κάποιος που βλέπει αυτό τον κώδικα υποθέτει πως την έχεις ορίσει σε κάποιο άλλο αρχείο, που θα συμπεριλάβεις στο compilation), κι έχεις και μια F η οποία είναι local στην main() και που στην ουσία μέσα στην main κάνει shadow την εξωτερική καθολική.
  • Like 1
Δημοσ.

Μαλιστα. Δηλαδη αυτο ειναι κατι ΜΟΝΟ για τον μεταγλωττιστη(οχι για τον χρηστη) και ουσιαστηκα, δινεις στον μεταγλωττιστη, μια "λιστα" με τα types και τα ονοματα, χωρις ομως να του λες τι κανει, η τι θα κανει, το καθενα απο αυτα. Σωστα ??

 

Πάνω κάτω ναι.

 

Μερικές φορές το κάνεις αυτό επίτηδες για να δημιουργήσεις αυτό που λέμε opaque type, μερικές φορές το κάνεις αναγκαστικά για να μη παραβιάσεις το ODR.

  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...