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

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

Δημοσ.

Εγώ δεν έχω καταλάβει την αρχική ερώτηση.

Π.χ. τι πρόβλημα υπάρχει σε κάτι σαν το παρακάτω...

 

>
int g_int; // global var, initialized to 0
...
int test( int *n )
{
*n = (g_int++) + 10;
}

Μάλλον η g_int θα καλείται σε πολλά σημεία. Πρέπει πάντα να είναι g_int++

  • Απαντ. 1,6k
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοσ.

 

Μάλλον η g_int θα καλείται σε πολλά σημεία. Πρέπει πάντα να είναι g_int++

 

Φαντάζει περιττό πάντως να φτιαχτεί ξεχωριστή συνάρτηση ή macro απλώς για να κάνει ένα ++ ... μια περίπτωση που μου έρχεται πρόχειρα, και θα είχε νόημα για κάτι τέτοιο (δεν ζητήθηκε στην ερώτηση) θα ήταν αν θέλαμε ας πούμε να γίνεται έλεγχος και auto-adjust στο εύρος τιμών της g_int.

 

Π.χ...

 

>
#include <limits.h>
...
#define INT_PLUS_PLUS(n)     ( (n) < INT_MAX ? ((n)++) : INT_MAX )

Δημοσ.

Καλύτερα μέσα σε συνάρτηση, πιο ασφαλή και πιο προστατευμένη η μεταβλητή.

Δεν μπορεί να γράψει κάποιος (κατά λάθος) GetValue()=a+b; ενώ μπορεί g+=a;

 

Με macro το μόνο κακό είναι ότι μπορείς να καλέσεις με οποιοδήποτε int.

Δημοσ.

Καλύτερα μέσα σε συνάρτηση, πιο ασφαλή και πιο προστατευμένη η μεταβλητή.

Δεν μπορεί να γράψει κάποιος (κατά λάθος) GetValue()=a+b; ενώ μπορεί g+=a;

 

Με macro το μόνο κακό είναι ότι μπορείς να καλέσεις με οποιοδήποτε int.

 

Yeap, αν κι εξαρτάται από το είδος της εφαρμογής. Τα συν/πλην των συναρτήσεων έναντι των macros είναι τεκμηριωμένα, οπότε μπορεί κανείς να επιλέξει ποιο ταιριάζει καλύτερα στο προτζεκτ του.

 

Για παράδειγμα, αν γράφεις speed-critical εφαρμογή (π.χ. για ενσωματωμένα συστήματα) και κάνεις πάρα πολλές κλήσεις στην GetValue() ίσως το speed-gain ενός macro έναντι της συνάρτησης να εξυπηρετεί καλύτερα (γλιτώνεις όλα τα σχετικά stack frames).

 

Από την άλλη, το macro σκάει αν κατά λάθος του κάνεις κάτι σαν το παρακάτω...

 

>
int n1 = INT_PLUS_PLUS(n2++) + 10;

 

Οπότε, αν το προτζεκτ δεν είναι speed-critical (ή/και δεν καλεί συχνά το εν λόγω) η συνάρτηση είναι σίγουρα καλύτερη επιλογή, λόγω του type-safeness που παρέχει.

 

Μια άλλη περίπτωση διλήμματος είναι αν θες π.χ. να διαχειριστείς abstractly διάφορους τύπους.

Για παράδειγμα για τα primitive data types (χωρίς έξτρα ελέγχους) αρκεί ένα...

 

>
#define PRIMTYPE_PLUS_PLUS(x)   ( (x)++ )

 

που δουλεύει με x οποιουδήποτε int (char included) ή float τύπου, ενώ με συναρτήσεις θες διαφορετική για κάθε τύπο (ή μία συνάρτηση, μάλλον variadic, με ένα έξτρα όρισμα προς αναγνώριση του τύπου και σημαντικά περισσότερο κώδικα στην υλοποίησή της... αν είναι variadic πάλι χάνεις το type-safeness, αν δεν είναι variadic μάλλον δεν είναι καλή ιδέα να υπάρχει μόνο μια συνάρτηση για όλους τους τύπους, αλλά να αποτελεί μέρος ενός γενικότερου abstract interface).

 

Γενικώς, macro ή συνάρτηση είναι ένα πολύ συχνό δίλημμα στην C, και προϋποθέτει λίγη σκέψη πριν αποφασίσει κανείς που, πότε και γιατί θα χρησιμοποιήσει είτε το ένα είτε το άλλο.

Δημοσ.

Νομιζω δεν εχω καταλαβει καλα τι ακριβως δειχνει ο τελεστης sizeof ... δεν εξηγειται αλλιως.

 

Λοιπον καταρχην το προτυπο της C λεει οταν χρησιμοποιεις εναν πινακα σε καποια εκφραση εκτος του sizeof και του & (και κατι αλλο που δεν εχει σημασια τωρα) μετατρέπεται σε δεικτη στο 1ο στοιχειο .. οκ το βλεπουμε και στις συναρτησεις αυτο οταν περναμε παραμετρους....

 

Οποτε άν int arr[4] τοτε sizeof(arr) = 16 bytes (implementation - defined ) .

Tωρα σε μια συναρτηση μέσα ο sizeof(arr) θα δώσει φυσικα το μεγεθος του δεικτη επειδη δεικτη στο 1ο στοιχειο βλεπει η συναρτηση.

 

Αυτο εδω ομως με μπερδεψε

 

http://c-faq.com/ary...ryparmsize.html

 

λογικα αυτο παιζει και δινει 4 μονο επειδη ο τυπος του δεικτη στο συστημα εκει ειναι 4

 

εμενα παντα 8 μου δινει παντως

 

>

#include<stdio.h>
void test(char []);

int main(void)
{
int arr2d[2][4] = { { 0 , 1 , 2 , 3 } , {4, 5 , 6 , 7}} , i=0 , (*p)[4] ;
int y=2 , *q = &y ;
char x[4];

//printf(" %ld " , sizeof(*p));

/*for( p = arr2d; p < arr2d + 2 ; p++)
{
printf(" %d " , (*p)[i]);

}

printf(" %p , %p , %p " , arr2d , &arr2d[0] , &arr2d[0][0]);*/

//printf(" %ld , %ld " , sizeof(q) , sizeof(x) );

test(x);

return 0;
}
void test(char x[])
{
printf(" %ld " , sizeof(x));

return ;
}

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

...

Αυτο εδω ομως με μπερδεψε

 

http://c-faq.com/ary...ryparmsize.html

 

λογικα αυτο παιζει και δινει 4 μονο επειδη ο τυπος του δεικτη στο συστημα εκει ειναι 4

 

εμενα παντα 8 μου δινει παντως

 

Πιθανότατα έχεις 64μπιτο λειτουργικό, με τους δείκτες να καταλαμβάνουν 64 bits = (8 bytes).

 

 

 

>

#include<stdio.h>
void test(char []);

int main(void)
{
int arr2d[2][4] = { { 0 , 1 , 2 , 3 } , {4, 5 , 6 , 7}} , i=0 , (*p)[4] ;
int y=2 , *q = &y ;
char x[4];

//printf(" %ld " , sizeof(*p));

/*for( p = arr2d; p < arr2d + 2 ; p++)
{
printf(" %d " , (*p)[i]);

}

printf(" %p , %p , %p " , arr2d , &arr2d[0] , &arr2d[0][0]);*/

//printf(" %ld , %ld " , sizeof(q) , sizeof(x) );

test(x);

return 0;
}
void test(char x[])
{
printf(" %ld " , sizeof(x));

return ;
}

 

 

Επισης το arr2d με το &arr2d[0] ειναι τα ιδια νομιζω... το &arr2d[0] που ουσιαστικα ο arr2d[0] ειναι το 1ο στοιχειο ο 1ος πινακας γραμμη ενος πινακα πινακων δεν ειναι διπλος δεικτης ... ετσι δεν ειναι ?

 

Δεν κοίταξα τον κώδικα, αλλά αν: int arr2d[NROWS][NCOLS]; τότε όντως τα arr2d και &arr2d[0] είναι τα ίδια, δηλαδή διπλοί δείκτες σε int. To arr2d[0] είναι μονός δείκτης σε int, δλδ η 1η γραμμή του arr2d (άρα ισούται με &arr2d[0][0] ).

 

Επισης εχω καταλαβει το κολπο με τις στηλες και οτι ο δεικτης μετακινειται κατα μια γραμμη επειδη sizeof(*p) = 16 bytes αλλα δεν μπορω να καταλαβω ο τυπος του (*p)[4] πχ ειναι int ή *p ?

 

Σύμφωνα με τον ορισμό που δίνεις:

 

>int (*p)[4];

 

ο p είναι ένας δείκτης σε πίνακα 4 ακεραίων, δηλαδή διπλός δείκτης (νομίζω δηλαδή, γιατί το συγκεκριμένο και μένα με μπερδεύει και πρέπει να καταφύγω στην τεκμηρίωση κάθε φορά που το συναντάω... δεν την έχω εύκαιρη τώρα ... edited below).

 

EDIT:

 

Yeap, δείκτης σε πίνακα 4 ακεραίων είναι ο p... μόλις το τσέκαρα: http://stackoverflow...-disambiguation

 

EDIT-2:

 

By the way, για τέτοιες περιπτώσεις δες το cdecl: http://www.cdecl.org/ (με έχει βοηθήσει πολύ και μένα... τελευταία φορά με κάτι const pointers of pointers, ή pointers of const pointers, κλπ).

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

Ευχαριστω ρε Χαρη. Απλα το θεμα ειναι οτι ενω δεν ειναι δηλωση διπλου δεικτη αυτη... τουλαχιστον ετσι μου ειπε καποιος αλλος.

 

Το (*p)[4] λεω... ενω δεν ειναι δηλωση διπλου συμπεριφερεται σαν διπλος.

 

Αν το δεις και πιο κατω στο βιβλιο του King βασικα να το παραθεσω εγω εδω :

 

>

for( p = &a[0] ; p < &a[NUM_ROWS]; p++)
.................

 

Πραγματικα θα καταληξουμε στο συμπερασμα οτι ο μεταγλωτιστης τον χρησιμοποιει σαν διπλο δεικτη

επειδη δεν θα μπορουσες να εκχωρησεις σε εναν μονο την διευθυνση ενος αλλου δεικτη. Για παραδειγμα.

 

>

int x=2 , y = 3 *p = &x , *q=&y ;

p = &q; /* ΛΑΘΟΣ */

p = q ; /* ΣΩΣΤΟ */

 

p.s στο μεταξυ με το που δινει το προγραμμα ο αλλος που βρισκει τις πολυπλοκες δηλωσεις αμεσως 83 Likes εφτασε στον θεο.... :D

 

Mου κανει εντυπωση παντως δεν θα μπορουσε να το γραψει ξεκαθαρα οτι ξερεις ειναι ενας διπλος δεικτης? Για να το απσαφηνισει 100% με την μια.

Δημοσ.

Ευχαριστω ρε Χαρη.

 

Τίποτα ρε συ :)

 

Απλα το θεμα ειναι οτι ενω δεν ειναι δηλωση διπλου δεικτη αυτη... τουλαχιστον ετσι μου ειπε καποιος αλλος.

 

Strictly speaking δεν είναι, αν ως "strictly speaking" θεωρήσουμε πως δεν είναι δήλωση δείκτη ούτε π.χ. η: int arr[5];

 

Το (*p)[4] λεω... ενω δεν ειναι δηλωση διπλου συμπεριφερεται σαν διπλος.

...

 

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

Δημοσ.

Σύμφωνα με τον ορισμό που δίνεις:

 

>int (*p)[4];

 

ο p είναι ένας δείκτης σε πίνακα 4 ακεραίων, δηλαδή διπλός δείκτης (νομίζω δηλαδή, γιατί το συγκεκριμένο και μένα με μπερδεύει και πρέπει να καταφύγω στην τεκμηρίωση κάθε φορά που το συναντάω... δεν την έχω εύκαιρη τώρα ... edited below).

 

EDIT:

 

Yeap, δείκτης σε πίνακα 4 ακεραίων είναι ο p... μόλις το τσέκαρα: http://stackoverflow...-disambiguation

 

EDIT-2:

 

By the way, για τέτοιες περιπτώσεις δες το cdecl: http://www.cdecl.org/ (με έχει βοηθήσει πολύ και μένα... τελευταία φορά με κάτι const pointers of pointers, ή pointers of const pointers, κλπ).

 

Όταν θες να βρεις ένα τύπο στα γρήγορα, όντως το cdecl βοηθάει πολύ. Για μη-έμπειρους χρήστες όμως προτείνω αντί για το cdecl να το προσπαθεί μόνος του ο καθένας για να το κατανοήσει καλύτερα. Ακόμη και σε πολύπλοκες εκφράσεις δεν είναι δύσκολος ο υπολογισμός. Μια γνωστή μέθοδος είναι η σπιράλ. Μια άλλη μέθοδος λέει το ίδιο με πιο απλά λόγια ότι δηλαδή πάντα πας δεξιά εκτός αν δεν μπορείς. Επειδή πάντα ξεκινάς από το όνομα της μεταβλητής, λίγο πιο δύσκολες είναι οι εκφράσεις χωρίς όνομα μεταβλητής.

 

int (*p)[4];

 

Ξεκινάμε από το p και πάμε δεξιά. Κλείνει παρένθεση οπότε δεν μπορούμε να πάμε δεξιά επομένως αναγκαστικά πάμε αριστερά και βλέπουμε δείκτη. Ξαναπάμε δεξιά και βλέπουμε πίνακα 4 στοιχείων. Δεν υπάρχει άλλο δεξιά οπότε πάμε αριστερά και βλέπουμε ακέραιο. Το p είναι δείκτης σε πίνακα 4 ακεραίων.

 

Σε προηγούμενη σελίδα είχε ρωτηθεί τι είναι το int (*funcptr)(double). Ξεκινάμε από το funcptr και λόγω παρένθεσης δεν μπορούμε να πάμε δεξιά οπότε αναγκαστικά πάμε αριστερά και βλέπουμε δείκτη. Εφόσον φτάσαμε στην αριστερή παρένθεση δεν είμαστε αναγκασμένοι να πάμε πλέον αριστερά οπότε πηγαίνουμε κανονικά δεξιά και βλέπουμε παρένθεση οπότε έχουμε συνάρτηση και τέλος πάμε αριστερά και έχουμε ακέραιο. Το funcptr είναι δείκτης σε συνάρτηση που δέχεται όρισμα τύπου double και επιστρέφει ακέραιο.

 

char *(*(**manoura[][8])())[];

 

Ένα μεγάλο παράδειγμα από εδώ. Όπως πάντα πάμε δεξιά και βλέπουμε πίνακα, συνεχίζουμε δεξιά και βλέπουμε πίνακα 8 στοιχείων. Πέσαμε σε παρένθεση οπότε δεν πάει άλλο δεξιά άρα συνεχίζουμε αριστερά και βλέπουμε δείκτη και ξανά δείκτη. Ως εδώ έχουμε ότι το manoura είναι "πίνακας με στοιχεία πίνακες 8 στοιχείων, το καθένα από τα οποία είναι δείκτης σε δείκτη σε ...."

 

Για ευκολία αντικαθιστώ όσο τμήμα λύσαμε με το παρακάτω char *(*new_manoura())[];

 

Όπως πάντα πηγαίνουμε δεξιά για όσο μπορούμε οπότε πάμε δεξιά και βλέπουμε το () άρα έχουμε συνάρτηση που παίρνει απροσδιόριστο αριθμό ορισμάτων. Πέσαμε σε δεξιά παρένθεση οπότε πάμε αναγκαστικά αριστερά και βλέπουμε δείκτη. Συνεχίζουμε δεξιά και βλέπουμε πίνακα και τελειώσαμε με το δεξιά οπότε πάμε αριστερά και βλέπουμε δείκτη σε χαρακτήρα.

 

Άρα η αρχική μας έκφραση μας λέει πως το manoura είναι πίνακας με στοιχεία πίνακες 8 στοιχείων, το καθένα από τα οποία είναι δείκτης σε δείκτη σε συνάρτηση που δέχεται απροσδιόριστο αριθμό ορισμάτων και επιστρέφει δείκτη σε πίνακα με στοιχεία δείκτες σε χαρακτήρα :)

 

Edit:

Ευχαριστω ρε Χαρη. Απλα το θεμα ειναι οτι ενω δεν ειναι δηλωση διπλου δεικτη αυτη... τουλαχιστον ετσι μου ειπε καποιος αλλος.

 

Το (*p)[4] λεω... ενω δεν ειναι δηλωση διπλου συμπεριφερεται σαν διπλος.

 

Αν το δεις και πιο κατω στο βιβλιο του King βασικα να το παραθεσω εγω εδω :

 

>

for( p = &a[0] ; p < &a[NUM_ROWS]; p++)
.................

 

Πραγματικα θα καταληξουμε στο συμπερασμα οτι ο μεταγλωτιστης τον χρησιμοποιει σαν διπλο δεικτη

επειδη δεν θα μπορουσες να εκχωρησεις σε εναν μονο την διευθυνση ενος αλλου δεικτη. Για παραδειγμα.

 

Δεν συμπεριφέρεται σαν διπλός δείκτης όχι. Αν είχαμε διπλό δείκτη με int **p αυτό θα σήμαινε ότι θα διάβαζε την τιμή του p, θα το χρησιμοποιούσε ως διεύθυνση θα διάβαζε την εκεί τιμή και θα χρησιμοποιούσε και εκείνη ως διεύθυνση για να προσπελάσει την τιμή που θέλουμε. Τώρα που έχουμε το int (*p)[4] διαβάζει την τιμή του p την χρησιμοποιεί ως διεύθυνση και διαβάζει απλά την εκεί τιμή καθώς και τις 3 συνεχόμενες αν θέλουμε. Αυτός είναι και ο λόγος που δεν μπορεί να χρησιμοποιηθεί διπλός δείκτης σε δισδιάστατο πίνακα.

Δημοσ.

ημιθεε κατσε γιατι μπερδευτηκα τωρα.... τελικα διαφωνεις με μενα και τον migf1 οτι προκειται για διπλο ?

 

Η εκει τιμη που διαβαζει ειναι διευθυνση δεικτη το a[0] ειναι δεικτης αρα το &a[0] ειναι δεικτης σε δεικτη.

 

Διαφωνεις καπου με αυτο?

 

@migf1 ναι συμφωνω οτι αυστηρα μιλοντας οι πινακες δεν ειναι δεικτες !

Δημοσ.

Η εκει τιμη που διαβαζει ειναι διευθυνση δεικτη το a[0] ειναι δεικτης αρα το &a[0] ειναι δεικτης σε δεικτη.

 

Διαφωνεις καπου με αυτο?

Λοιπον καταρχην το προτυπο της C λεει οταν χρησιμοποιεις εναν πινακα σε καποια εκφραση εκτος του sizeof και του & (και κατι αλλο που δεν εχει σημασια τωρα) μετατρέπεται σε δεικτη στο 1ο στοιχειο .. οκ το βλεπουμε και στις συναρτησεις αυτο οταν περναμε παραμετρους....

 

Εσύ το είπες πριν πως όταν έχουμε το & _δεν_ μετατρέπεται σε δείκτη οπότε το a[0] όσον αφορά το & δεν είναι δείκτης αλλά πίνακας με NUM_COLS στοιχεία.

 

Edit:

 

>
int a[3][5];

printf("&a[0]=%p\n", &a[0]);
printf("&a[0] + 1=%p\n", &a[0]+1);

Έξοδος:
&a[0]=0x07c0
&a[0] + 1=0x07d4

Όπως βλέπεις, η διαφορά δεν είναι 8 bytes όπως θα έπρεπε να είναι για ένα δείκτη σε 64bit αλλά 20 bytes δηλαδή 5 φορές το μέγεθος του int γιατί το &a[0] έχει τύπο "πίνακας 5 ακεραίων" οπότε η αριθμητική δουλεύει με αυτό (κανονικά στο %p format πρέπει να δίνουμε void δείκτη αλλά δεν το έβαλα επίτηδες).

Δημοσ.

Εσύ το είπες πριν πως όταν έχουμε το & _δεν_ μετατρέπεται σε δείκτη οπότε το a[0] όσον αφορά το & δεν είναι δείκτης αλλά πίνακας με NUM_COLS στοιχεία.

 

Edit:

 

 

>
int a[3][5];

printf("&a[0]=%p\n", &a[0]);
printf("&a[0] + 1=%p\n", &a[0]+1);

Έξοδος:
&a[0]=0x07c0
&a[0] + 1=0x07d4

 

 

Όπως βλέπεις, η διαφορά δεν είναι 8 bytes όπως θα έπρεπε να είναι για ένα δείκτη σε 64bit αλλά 20 bytes δηλαδή 5 φορές το μέγεθος του int γιατί το &a[0] έχει τύπο "πίνακας 5 ακεραίων" οπότε η αριθμητική δουλεύει με αυτό (κανονικά στο %p format πρέπει να δίνουμε void δείκτη αλλά δεν το έβαλα επίτηδες).

 

Από την άλλη μεριά όμως...

 

>
#include <stdio.h>

int main( void )
{
int a[3][5], **p = a;

printf( "%zu\n", sizeof(&a[0]) );
printf( "%zu\n", sizeof(p) );

return 0;
}

 

Έξοδος (σε 32μπιτη πλατφόρμα)...

>
4
4

 

Καθώς επίσης και ...

 

>
#include <stdio.h>

void print_next( int a[] )
{
   printf( "next: %p\n", ++a );
}

int main( void )
{
   int a[3][5], **p = a;

   printf("&a[0]=%p\n", &a[0]);
   print_next( &a[0] );

   return 0;
}

 

Με έξοδο (σε 32μπιτη πλατφόρμα)...

>
&a[0]=0022ff10
next: 0022ff14

 

Δηλαδή κατά περιπτώσεις οι πίνακες συμπεριφέρονται ως/μετατρέπονται σε δείκτες.

 

Σε γενικές γραμμές, οι πίνακες είναι δείκτες που όμως δεν μπορούν χρησιμοποιηθούν ως lvalues.

Δημοσ.

Εσύ το είπες πριν πως όταν έχουμε το & _δεν_ μετατρέπεται σε δείκτη οπότε το a[0] όσον αφορά το & δεν είναι δείκτης αλλά πίνακας με NUM_COLS στοιχεία.

 

Edit:

 

>
int a[3][5];

printf("&a[0]=%p\n", &a[0]);
printf("&a[0] + 1=%p\n", &a[0]+1);

Έξοδος:
&a[0]=0x07c0
&a[0] + 1=0x07d4

Όπως βλέπεις, η διαφορά δεν είναι 8 bytes όπως θα έπρεπε να είναι για ένα δείκτη σε 64bit αλλά 20 bytes δηλαδή 5 φορές το μέγεθος του int γιατί το &a[0] έχει τύπο "πίνακας 5 ακεραίων" οπότε η αριθμητική δουλεύει με αυτό (κανονικά στο %p format πρέπει να δίνουμε void δείκτη αλλά δεν το έβαλα επίτηδες).

 

Εγω δεν μπορω να καταλαβω το εξης.... εφοσον το προτυπο λεει οτι εκτος sizeof και & ο πινακας δεν μετατρεπεται σε δεικτη

/*τοτε σε εναν απλο μονοδιαστατο πινακα και ενα loop με &a μεσα τοτε &πινακας τι ειναι ακριβως?*/ :P

 

Διευθυνση δινει αρα ειναι δεικτης προς αυτη την διευθυνση του στοιχειου i .... εκτος και αν θυμηθουμε οτι δεν ειναι παντα ενας δεικτης ιδιος - ισοδυναμος με μια διευθυνση. Πραγματικα στους μονοδιαστατους δεν φαινεται τοσο το λεπτο αυτο σημειο οσο στους 2-D .

 

P.S Ακυρο το boldarismeno !!!! Ολα οκ απλα εχω ζαλιστει λιγο :P

Δημοσ.

 

Από την άλλη μεριά όμως...

 

>
#include <stdio.h>

int main( void )
{
int a[3][5], **p = a;

printf( "%zu\n", sizeof(&a[0]) );
printf( "%zu\n", sizeof(p) );

return 0;
}

 

Έξοδος (σε 32μπιτη πλατφόρμα)...

>
4
4

Που είναι το παράξενο σε αυτό ? Το μέγεθος του δείκτη είναι 4 οπότε παίρνεις 4. Αυτό που είπα εγώ (ίσως να μην το είπα τόσο καλά απλά) είναι ότι δεν έχεις δείκτη σε δείκτη σε int αλλά δείκτη σε πίνακα 5 στοιχείων int.

 

Καθώς επίσης και ...

 

>
#include <stdio.h>

void print_next( int a[] )
{
   printf( "next: %p\n", ++a );
}

int main( void )
{
   int a[3][5], **p = a;

   printf("&a[0]=%p\n", &a[0]);
   print_next( &a[0] );

   return 0;
}

 

Με έξοδο (σε 32μπιτη πλατφόρμα)...

>
&a[0]=0022ff10
next: 0022ff14

 

Δηλαδή κατά περιπτώσεις οι πίνακες συμπεριφέρονται ως/μετατρέπονται σε δείκτες.

 

 

Και πάλι που είναι το παράξενο ? Μήπως ήθελες να δώσεις κάποιο λίγο διαφορετικό παράδειγμα ? Εδώ δηλώνεις μια συνάρτηση να δέχεται μονοδιάστατο πίνακα δηλαδή ουσιαστικά, όπως έχουμε πει, μια συνάρτηση που δέχεται ένα δείκτη σε ακέραιο και χρησιμοποιείς την έκφραση ++a. Έτσι ο compiler θα αυξήσει κατά 4. Το ό,τι στην main περνάς στη συνάρτηση το &a[0] που αναφέρεται σε δισδιάστατο πίνακα δεν έχει καμμία σχέση και το αποτέλεσμα θα ήταν +4 οτιδήποτε και να περνούσες στη συνάρτηση. Αν μέσα στη συνάρτηση αντί απλά να έχεις ++a, προσπέλαυνες την τιμή του θα είχες πρόβλημα το οποίο στο λέει και ο compiler. Στον gcc παίρνω αυτό:

>
In function ‘main’:
10:24: προειδοποίηση: initialization from incompatible pointer type [enabled by default]
13:5: προειδοποίηση: passing argument 1 of ‘print_next’ from incompatible pointer type [enabled by default]
3:6: σημείωση: expected ‘int *’ but argument is of type ‘int (*)[5]’
10:20: προειδοποίηση: unused variable ‘p’ [-Wunused-variable]

Όπως βλέπουμε, ο gcc αναφέρει αυτό που είπα πριν λίγο και που ανέφερα και στο προηγούμενο μήνυμά μου αλλά ίσως δεν το εξήγησα σωστά. Το &a[0] είναι δείκτης σε πίνακα 5 ακεραίων.

Επισκέπτης
Αυτό το θέμα είναι πλέον κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...