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

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

Δημοσ.

Προσπαθώ να καταλάβω τους pointers σε arrays και μπερδεύομαι λίγο ή πολύ

δηλαδή

Το παρακάτω κάνει την γραμμή 2 και τη στήλη 2 ενός array 5*5  0

#include<stdio.h>

int main()
{
  int a[5][5]={{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}};
  int *q;
  int (*p)[5];
  
  for (q=a[2];q<a[2]+5;q++)
    *q=0;
  
  for (p=&a[0];p<&a[5];p++)
    (*p)[2]=0;
    
  for (int i=0;i<5;i++)
  {
    for (int j=0;j<5;j++)
      printf("%4d",a[i][j]);
   printf("\n");
  }
  return 0;
} 

Γιατί στον pointer q κάνει ανάθεση της μνήμης με q=a[2] και στον pointer p με p=&a[0] δεν θα έπρεπε να γίνει με p=a[0] και αυτό.

είδα ένα tutorial αλλά πάλι το χάνω

 

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

 

 

Προσπαθώ να καταλάβω τους pointers σε arrays και μπερδεύομαι λίγο ή πολύ

δηλαδή

Το παρακάτω κάνει την γραμμή 2 και τη στήλη 2 ενός array 5*5 0

#include<stdio.h>

int main()
{
  int a[5][5]={{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}};
  int *q;
  int (*p)[5];
  
  for (q=a[2];q<a[2]+5;q++)
    *q=0;
  
  for (p=&a[0];p<&a[5];p++)
    (*p)[2]=0;
    
  for (int i=0;i<5;i++)
  {
    for (int j=0;j<5;j++)
      printf("%4d",a[i][j]);
   printf("\n");
  }
  return 0;
}
Γιατί στον pointer q κάνει ανάθεση της μνήμης με q=a[2] και στον pointer p με p=&a[0] δεν θα έπρεπε να γίνει με p=a[0] και αυτό.

είδα ένα tutorial αλλά πάλι το χάνω

Σχετικά με το:
p=&a[0]
Το a[0] είναι ένας pointer που δείχνει σε έναν μονοδιάστατο πίνακα(Στο πρώτο του στοιχείο). Άρα τι λέει ουσιαστικά; Στο p (που είναι δείκτης σε πίνακα 5 θέσεων) βάλε την διεύθυνση του πίνακα(της αρχής του) που δείχνει το a[0] ή αν θες να το σκέφτεσαι αλλιώς την 0 γραμμή του δισδιάστατου πίνακα a.

Γενικότερα να σκέφτεσαι ότι ένα * είναι δείκτης(που μπορεί να είναι και δείκτης σε πίνακα ουσιαστικά απλά δείχνει στο πρώτο του στοιχείο και όχι μόνο σε μία τιμή) και δύο * είναι δείκτης σε δείκτη(και δείκτης σε πίνακα άρα δισδιάστατος πίνακας).

Δηλαδή το

int (*p)[5];
γράφεται και:

int p[][5]
Τώρα όσο αναφορά το q είναι pointer σε αριθμό (είπαμε μπορεί να δείξει και σε πίνακα και ως τέτοιος χρησιμοποιείται και εδώ) και τον χρησιμοποιεί ως:
q = a[2]
γιατί θέλει να αποκτήσει πρόσβαση στην τιμή του a[2](ως δείκτης) που είναι ένας μονοδιάστατος πίνακας για να την αλλάξει.

Γενικότερα οι δισδιάστατοι πίνακες αποθηκεύονται σειριακά στην μνήμη ανά γραμμή για αυτό και βλέπεις ότι γράφει:

for(q = a[2];q<a[2]+5;q++){}
για να προσπελάσει τα στοιχεία που ξεκινάνε από την αρχή της γραμμής a[2] και τα επόμενα 5 στοιχεία(Δηλαδή όλη την γραμμή) Επεξ/σία από kaliakman
  • Like 1
Δημοσ.

int (*p)[5];
γράφεται και:

int p[][5]

είτε

int **p

Είναι κάπως επικίνδυνο να συγκρίνεις δείκτες και πίνακες. Σε πολλές περιπτώσεις ο πίνακας θυμίζει δείκτη (array indexing), και σε κάποιες μετατρέπεται σε δείκτη (όταν περνάει σαν παράμετρος πχ) αλλά είναι διαφορετικοί τύποι δεδομένων, και σημαίνουν διαφορετικά πράματα. Ο δείκτης περιέχει την τιμή μιας θέσης μνήμης, και ο πίνακας είναι απλά μία σειρά από αντικείμενα (στην C ο όρος αντικείμενο δεν έχει την ίδια σημασία με μία OOP γλώσσα).

 

Στην περίπτωσή σου, αν γράψεις κάτι τέτοιο για παράδειγμα:

int (*p)[5];
int **z;

.....

z = p;

ή

p = z;

δεν θα δουλέψει, γιατί το **z και το (*p)[5] είναι διαφορετικοί τύποι δεδομένων. Όπως επίσης και το "int array[5];" μαζί με το "int *ptr;" είναι διαφορετικοί τύποι δεδομένων. Στο c-faq έχει ολόκληρη κατηγορία μόνο για αυτές τις "παρεξηγήσεις" μεταξύ πινάκων και δεικτών

http://c-faq.com/.xx/aryptr/ αξίζει να το ρίξετε μια ματιά.

Δημοσ.

Είναι κάπως επικίνδυνο να συγκρίνεις δείκτες και πίνακες. Σε πολλές περιπτώσεις ο πίνακας θυμίζει δείκτη (array indexing), και σε κάποιες μετατρέπεται σε δείκτη (όταν περνάει σαν παράμετρος πχ) αλλά είναι διαφορετικοί τύποι δεδομένων, και σημαίνουν διαφορετικά πράματα. Ο δείκτης περιέχει την τιμή μιας θέσης μνήμης, και ο πίνακας είναι απλά μία σειρά από αντικείμενα (στην C ο όρος αντικείμενο δεν έχει την ίδια σημασία με μία OOP γλώσσα).

 

Στην περίπτωσή σου, αν γράψεις κάτι τέτοιο για παράδειγμα:

int (*p)[5];
int **z;

.....

z = p;

ή

p = z;
δεν θα δουλέψει, γιατί το **z και το (*p)[5] είναι διαφορετικοί τύποι δεδομένων. Όπως επίσης και το "int array[5];" μαζί με το "int *ptr;" είναι διαφορετικοί τύποι δεδομένων. Στο c-faq έχει ολόκληρη κατηγορία μόνο για αυτές τις "παρεξηγήσεις" μεταξύ πινάκων και δεικτών

http://c-faq.com/.xx/aryptr/ αξίζει να το ρίξετε μια ματιά.

Συμφωνώ και ευχαριστώ για την επεξηγηση. Ήθελα να αναφέρω και για την δυναμική δέσμευση για τον διπλό pointer αλλά δεν ήθελα να το μπερδέψω περισσότερο και έσβησα κάποια πράγματα σε edit που έκανα.

Δημοσ.

Το ότι δεν μπορούμαι να κάνουμε pointer arithmetic με το όνομα ενός array (όταν το χρησιμοποιούμαι ως pointer) το έχω κατανοήσει. 

 

Το βιβλίο που διαβάζω "c programming a modern approach" είναι αρκετά καλό  αλλά αφιερώνει στους πολυδιάστατους λίγες μόνο σελίδες. 

Γενικά παντώς αυτό το ανακάτεμα pointers με arrays names είναι λίγο μπέρδεμα για μένα. Ίσως όταν λύνω τις ασκήσεις το αντιληφθώ λίγο καλύτερα. 

 

Οκ το συμπέρασμα γιατί δεν μπορώ να κάνω το p=a[0] στο παράδειγμα μου. Το πρώτο είναι pointer σε 5 ints και το δεύτερο σε 1 int  (στο a[0][0] συγκεκριμένα), ξεκάθαρο. 

Ενώ με το q,  το q είναι pointer σε ένα int,  το a[2] είναι pointer σε ένα int (στο στοιχείο a[2][0]) οπότε είναι οκ το q=a[2].

 

Κατανοητό μέχρι στιγμής ευχαριστώ

Δημοσ.

Σχετικά με το:

p=&a[0]
Το a[0] είναι ένας pointer που δείχνει σε έναν μονοδιάστατο πίνακα(Στο πρώτο του στοιχείο). Άρα τι λέει ουσιαστικά; Στο p (που είναι δείκτης σε πίνακα 5 θέσεων) βάλε την διεύθυνση του πίνακα(της αρχής του) που δείχνει το a[0] ή αν θες να το σκέφτεσαι αλλιώς την 0 γραμμή του δισδιάστατου πίνακα a.

 

Οκ το συμπέρασμα γιατί δεν μπορώ να κάνω το p=a[0] στο παράδειγμα μου. Το πρώτο είναι pointer σε 5 ints και το δεύτερο σε 1 int  (στο a[0][0] συγκεκριμένα), ξεκάθαρο. 

 

Κατανοητό μέχρι στιγμής ευχαριστώ

Όπως είπε και ο Gikoskos, άλλο πράγμα είναι ο πίνακας και άλλο ο δείκτης. Το a[0] δεν είναι δείκτης ούτε επίσης το a[0] είναι δείκτης σε 1 int στο a[0][0]. Από που προέκυψε αυτό το συμπέρασμα ?

 

#include<stdio.h>

int main()
{
  int a[5][5]={{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}};
  int *q;
  int (*p)[5];
  
  printf("a = %zu, &a = %zu\n", sizeof a[0], sizeof &a[0]);
  
  return 0;
} 
Έξοδος:
% ./a.out 
a = 20, &a = 8
Όπως βλέπεις, το μέγεθος του a[0] είναι 20 (5 int στοιχεία το καθένα των οποίων καταλαμβάνει 4 bytes σε εμένα). Όρισες ένα "δισδιάστατο" πίνακα δηλαδή ένα πίνακα με στοιχεία πίνακες οπότε αυτό που παίρνεις είναι πίνακας και όχι δείκτης (για αυτό κιόλας δίνει μέγεθος 20).

 

Η δήλωση του p έχει παρενθέσεις οπότε ο τύπος του είναι δείκτης σε πίνακα 5 θέσεων με στοιχεία int. Δηλαδή δήλωσες ένα δείκτη οπότε χρειάζεσαι να του θέσεις την σωστή τιμή η οποία είναι η &a[0].

 

Δες τον παρακάτω κώδικα σε ας πούμε C++:

#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
  int a[5][5]={{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}};
  int (*p)[5];

  cout << "a = " << typeid(a).name() << endl;
  cout << "a[0] = " << typeid(a[0]).name() << endl;
  cout << "a[0][0] = " << typeid(a[0][0]).name() << endl;
  cout << "&a[0] = " << typeid(&a[0]).name() << endl;
  cout << "p = " << typeid(p).name() << endl;
  cout << "p and a[0] compatible ? " << (typeid(p) == typeid(a[0])) << endl;
  cout << "p and &a[0] compatible ? " << (typeid(p) == typeid(&a[0])) << endl;
  return 0;
} 
Έξοδος:
a = A5_A5_i
a[0] = A5_i
a[0][0] = i
&a[0] = PA5_i
p = PA5_i
p and a[0] compatible ? 0
p and &a[0] compatible ? 1
Όπως βλέπεις, το a δεν έχει καμμία σχέση με δείκτες αλλά είναι πίνακας πινάκων και το a[0] είναι και αυτό πίνακας.
  • Like 1
Δημοσ.

Όπως είπε και ο Gikoskos, άλλο πράγμα είναι ο πίνακας και άλλο ο δείκτης. Το a[0] δεν είναι δείκτης ούτε επίσης το a[0] είναι δείκτης σε 1 int στο a[0][0]. Από που προέκυψε αυτό το συμπέρασμα ?

 


Μη μου το χαλάς τώρα που άρχισα να το ξεδυαλύνω

 

δεν είπαμε δείκτης είπαμε pointer ή τέλος πάντων μπορεί να χρησιμοποιηθεί σαν pointer

Ότι δεν μπορούμε να κάνουμε με αυτό pointer arithmetic το ξέρω.

 

Μή μου πεις να αλλάξω βιβλίο

Το έχει γράψει κάποιος K.N. King το 2008 και έχει καλές κρητικές

Στη c++ δεν έχω ιδέα πως δουλεύει

post-372633-0-21765500-1491938843_thumb.jpg

Δημοσ.

δεν είπαμε δείκτης είπαμε pointer ή τέλος πάντων μπορεί να χρησιμοποιηθεί σαν pointer

Δείκτης και pointer είναι διαφορετικές έννοιες δηλαδή ?

 

Μή μου πεις να αλλάξω βιβλίο

Το έχει γράψει κάποιος K.N. King το 2008 και έχει καλές κρητικές

Πότε σύστησα να αλλάξεις βιβλίο ? Ίσα ίσα το συγκεκριμένο βιβλίο το προτείνουμε όλη την ώρα στο φόρουμ επειδή είναι πολύ καλό.

 

Μη μου το χαλάς τώρα που άρχισα να το ξεδυαλύνω

Οκ τότε να μην στο χαλάσω αφού το ξεδυάλυνες. Πάω πάσο.
Δημοσ.

Δείκτης και pointer είναι διαφορετικές έννοιες δηλαδή ?

 

Πότε σύστησα να αλλάξεις βιβλίο ? Ίσα ίσα το συγκεκριμένο βιβλίο το προτείνουμε όλη την ώρα στο φόρουμ επειδή είναι πολύ καλό.

 

Οκ τότε να μην στο χαλάσω αφού το ξεδυάλυνες. Πάω πάσο.

 

 

 

Τελικά είναι κάτι λάθος στο βιβλίο ή κατάλαβα κάτι λάθος;

 

Το μη μου το χαλάς δεν είναι κυριολεκτικό. Να μου το χαλάσεις 1000 φορές αν είναι κάτι λάθος. 

 

Συγνώμη για το ύφος μου δεν περίμενα να παρεξηγηθεί έτσι η πρόθεση μου ήταν φιλική.

Δημοσ.

Το παρακάτω από το ίδιο βιβλίο έρχεται να ξεκαθαρίσει (μπερδέψει)   :shock: ακόμα περισσότερο τα πράγματα 

είναι το όνομα του array ένας pointer ή όχι

 

post-372633-0-76047200-1491986441_thumb.jpg

Δημοσ.

Το παρακάτω από το ίδιο βιβλίο έρχεται να ξεκαθαρίσει (μπερδέψει)   :shock: ακόμα περισσότερο τα πράγματα 

είναι το όνομα του array ένας pointer ή όχι

Διαβάζοντας το προηγούμενο τμήμα που έβαλες, ήμουν έτοιμος να γράψω "ναι το βιβλίο είναι λάθος". Η έκφραση "for any two-dimensional array a, the expression a is a pointer to the first element in row i" τυπικά είναι λάθος. Όπως (ελπίζω να ) σου έδειξε ο κώδικας που έβαλα πριν, το a είναι πίνακας και όχι δείκτης.

 

Το επόμενο που σκέφτηκα ήταν πώς θα το διατύπωνα εγώ και εννοείται πως θα το διατύπωνα χειρότερα. Όταν γράφεις ένα βιβλίο, πρέπει καλώς ή κακώς να κάνεις κάποιες συμβάσεις και να γράψεις καταχρηστικά κάποια πράγματα που δεν ισχύουν, χάριν ευκολίας. Αλλιώς θα πρέπει σε κάθε γραμμή να έχεις και μια υποσημείωση που να λέει "για την ακρίβεια συμβαίνει το τάδε πράγμα" το οποίο θα είναι πάρα πολύ έξτρα πληροφορία που θα μπερδέψει τον αναγνώστη.

 

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

 

Ας έρθουμε τώρα στο δεύτερο κομμάτι που έβαλες. "Technically, the name of an array isn't a pointer; rather, the C compiler converts it to a pointer when necessary. To see this difference more clearly, consider what happens when we apply the sizeof operator to an array a."

 

Σαν έννοια και σαν ιδέα (και σαν τύπος της C), οι πίνακες είναι διαφορετικοί από τους δείκτες. Σε κάποιες εκφράσεις, ο compiler μετατρέπει για ευκολία το πίνακα σε δείκτη σε κάποιο στοιχείο οπότε είναι σαν να έγραφες μια έκφραση με δείκτη. Ας δούμε το κομμάτι του προτύπου που διέπει το συγκεκριμένο θέμα.

 

Except when it is the operand of the sizeof operator or the unary & operator, or is a

string literal used to initialize an array, an expression that has type ‘‘array of type’’ is

converted to an expression with type ‘‘pointer to type’’ that points to the initial element of

the array object and is not an lvalue. If the array object has register storage class, the

behavior is undefined.

Εκτός από τους τελεστές sizeof και &, σε οποιαδήποτε άλλη περίπτωση έχεις "πίνακα σε κάτι" αυτό μετατρέπεται αυτόματα σε "δείκτης σε κάτι" και δείχνει στο πρώτο στοιχείο.

 

Αυτό το κάτι είναι που μπερδεύει τον περισσότερο κόσμο γιατί στο 99% των περιπτώσεων χρησιμοποιούμε μονοδιάστατους πίνακες και απλούς δείκτες. Εκεί τα πράγματα είναι εύκολα και η συμπεριφορά είναι σχεδόν η ίδια το οποίο μπερδεύει πολύ κόσμο. Ας δούμε τον παρακάτω κώδικα.

 

#include<stdio.h>

int main()
{
  int b[5];
  int a[5][5];

  int *p, *q, (*pa)[5];

  p = b;
  q = &b[0];

  p = a[2];
  q = &a[2][0];

  pa = &b;
  pa = &a[2];
  pa = a[2];
  
  return 0;
}

% cc -Wall tmp.c 
tmp.c: In function ‘main’:
tmp.c:18:6: προειδοποίηση: assignment from incompatible pointer type [-Wincompatible-pointer-types]
   pa = a[2];
      ^
Όλες οι περιπτώσεις εκτός από την τελευταία είναι σωστές. Γιατί όμως είναι σωστές ? Ας τις πάρουμε μία-μία.

 

  int b[5];
  int a[5][5];
  int *p, *q, (*pa)[5];

  p = b;
  q = &b[0];
Έχουμε την μεταβλητή b η οποία είναι "πίνακας σε 5 ints". Εφόσον την χρησιμοποιείς σε μια έκφραση (που δεν έχει & ή sizeof), ο compiler το μετατρέπει σαν να είχες ένα "δείκτη σε 5 ints" (δηλαδή δείκτη σε int μια και η c δεν έχει έλεγχο ορίων) που να δείχνει στο πρώτο στοιχείο και δίνει την διεύθυνση του στον δείκτη p. Δηλαδή χωρίς να το ξέρεις έγραψες "&b[0]" που φαίνεται στην δεύτερη έκφραση με το q.

 

  int b[5];
  int a[5][5];
  int *p, *q, (*pa)[5];

  p = a[2];
  q = &a[2][0];
Εδώ έχουμε την πρώτη περίπτωση από τον δικό σου κώδικα που είχες q=a[2]. Τι τύπο έχει η έκφραση a[2] ? Αν προσέξεις στο προηγούμενο μήνυμά μου, η έκφραση a[2] έχει τύπο "πίνακας σε 5 ints" (το 5 από την δεύτερη διάσταση φυσικά) οπότε και αυτό μετατρέπεται σε "δείκτης σε 5 ints" ο οποίος δείχνει στο 1ο στοιχείο της 3ης γραμμής. Δηλαδή πάλι έχεις ένα δείκτη τον οποίο θέτεις ως τιμή σε ένα δείκτη σε int που είναι το p. Και πάλι, ο compiler θεωρεί ότι έγραψες την δεύτερη μορφή με το q.

 

  int b[5];
  int a[5][5];
  int *p, *q, (*pa)[5];

  pa = &b;
  pa = &a[2];
  pa = a[2];
Ας έρθουμε τώρα στο φλέγον θέμα που είναι αυτό που δεν σου έπαιζε. Η διαφοροποίηση εδώ είναι ότι έχεις το pa (p στον δικό σου κώδικα) το οποίο δεν είναι απλός δείκτης σε int αλλά δείκτης σε πίνακα από 5 ints.

 

Ας δούμε πρώτα την τελευταία γραμμή που είναι αυτή που είχες εσύ και που δεν παίζει. Η μετατροπή όπως φαντάζεσαι είναι ακριβώς ίδια με τις άλλες δύο περιπτώσεις. Το a[2] για άλλη μια φορά γίνεται "δείκτης σε int" και είναι σαν να είχες γράψει pa = &a[2][0]. Δηλαδή εσύ προσπαθείς να θέσεις ένα "δείκτη σε int" σε ένα "δείκτη σε πίνακα από 5 ints" το οποίο αποτυγχάνει γιατί οι τύποι δεν είναι συμβατοί. Το ίδιο πρόβλημα θα είχες και αν είχες int **p. Μόνο στον μονοδιάστατο πίνακα, τα πράγματα είναι ψιλοισοδύναμα.

 

Οι δύο πρώτες γραμμές τώρα με τα &b και &a[2] γιατί παίζουν ? Γιατί όπως μας είπε το πρότυπο, η μετατροπή πίνακας -> δείκτης δεν γίνεται στους τελεστές sizeof και &. Η έκφραση &b μπορεί να δείχνει στην ίδια διεύθυνση μνήμης όπως το 1ο στοιχείο (&b[0]) αλλά εφόσον δεν υπάρχει μετατροπή, ο τύπος διατηρείται. Δηλαδή το &b έχει τύπο ίδιο με το b δηλαδή "πίνακας σε 5 ints" οπότε τον ίδιο τύπο με τον δείκτη pa. Ομοίως και το &a[2] έχει τύπο "πίνακας σε 5 ints".

  • Like 4
Δημοσ.

imitheos 

 

Κατ αρχήν σε ευχαριστώ για το χρόνο σου 

Να ξεκαθαρίσω κάτι που νομίζω έχεις παρανοήσει 

Ο κώδικας που είχα στην αρχή είναι από το βιβλίο όχι αυτούσιος αλλά κομμάτια συραμμένα και όχι ότι δεν δουλεύει, δουλεύει κανόνικα, (στον δικό μου υπολογιστή τουλάχιστον) το ερώτημα μου ήταν γιατί δουλεύει  :-) , για να κατανοήσω τους δείκτες (pointers) , γιατί χρησιμοποιεί δύο διαφορετικές τεχνικές για να πάρει την γράμμη και τη στήλη του array; 

 

Νομίζω σε αυτή τη φάση το έχω κατανοήσει αν όχι σε βάθος τουλάχιστον στο θέμα της χρήσης. Προσπαθώ να καταλάβω και αυτά που μου γράφεις .

 

To συμπέρασμα που έβγαλα φωναχτά  :-)  πιο πάνω μέχρι στιγμής δουλεύει με τις ασκήσεις 

Δημοσ.

Κατ αρχήν σε ευχαριστώ για το χρόνο σου 

Να ξεκαθαρίσω κάτι που νομίζω έχεις παρανοήσει 

Ο κώδικας που είχα στην αρχή είναι από το βιβλίο όχι αυτούσιος αλλά κομμάτια συραμμένα και όχι ότι δεν δουλεύει, δουλεύει κανόνικα, (στον δικό μου υπολογιστή τουλάχιστον) το ερώτημα μου ήταν γιατί δουλεύει  :-) ,

Ναι έχεις δίκιο ότι δουλεύει. Είχα στο νου μου την ερώτηση που έκανες "γιατί χρειάζεται το & στο 2ο ενώ στο 1ο δεν χρειάζεται" και αυτό εννοούσα όταν έγραψα "δεν παίζει" ότι δηλαδή δεν παίζει χωρίς το &.

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

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

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

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

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

Σύνδεση

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

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