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

ΕΡΩΤΗΣΗ ΣΕ ΠΡΟΓΡΑΜΜΑ ΣΕ C


ColdFusion

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

Δημοσ.

Έχω φτιάξει το παρακάτω πρόγραμμα αλλά κάτι δεν μου πάει καλά με τη συνάρτηση!

Μπορεί κάποιος να βοηθήσει γιατί δεν μπορώ να βρώ το λάθος !!

Ευχαριστώ!

>#include <stdio.h>
#include <stdlib.h>
#define v 4
int find(int array[v]);
main()
{
     int pinakas[4]={1,2,3,4};
     int a;
     a=find(pinakas[4]);
     
     printf("----->%d",a);
     system("pause");


}



//function
int find(int array[v])

{
   int i,k,o;
   o=0;
   
   for (i=0;i<=v-1;i++)
   
   {
   
      
   k=array[i];
   
   if (k<0) o++;
}
   
   return  o;
}

Δημοσ.

>int find(int array[v]);

Εδώ ορίζεις πως η συνάρτηση θα δέχεται ως argument τον υποπίνακα του πίνακα array, από το κελί array[v] και πέρα...το οποίο παρεμπιπτόντως είναι και χοντρό out of bounds error...

 

>	a=find(pinakas[4]);

Εδώ καλείς τη συνάρτηση, περνώντας άλλου τύπου argument, έναν int (το στοιχείο pinakas[4]). Λογικά, ο compiler σου θα πρέπει να σε προειδοποίησε γι' αυτό. Π.χ. ο GCC βγάζει το εξής warning:

warning: passing arg 1 of `find' makes pointer from integer without a cast

...το οποίο δηλώνει την ανακολουθία που εξήγησα παραπάνω.

 

 

Πώς θα έγραφα εγώ το πρόγραμμα:

 

>
#include <stdio.h>

int find(int*, int);

int main(void) {
int pinakas[4] = {1, 2, 3, 4};

printf("----->%d\n", find(pinakas, 4));

return 0;
}

int find(int *array, int size) {
int i, negatives = 0;

for(i = 0; i < size; i++) {
	if(array[i] < 0) negatives++;
}

return negatives;
}

 

Αν προσέξεις, έφυγε και το define statement για το μέγεθος του πίνακα, γιατί η υλοποίηση με τέτοιον τρόπο είναι κακή πρακτική. Όταν θέλεις σε μία συνάρτηση να γνωρίζεις το μέγεθος του πίνακα, θα το περνάς ως έξτρα όρισμα. Έτσι, θα σου γίνει συνήθεια και θα το έχεις φυσικό ως διαδικασία όταν αργότερα θα μάθεις να χρησιμοποιείς μη στατικού μεγέθους πίνακες.

Δημοσ.

Σε ευχαριστώ για την απάντηση είναι αρκετά λεπτομερής.Στην περίπτωση όμως που θέλω να περάσω ως όρισμα ένα ολόκληρο πίνακα τη κάνω ?

Δημοσ.

Ωραία. Αν θέλεις να περάσεις ολόκληρο τον πίνακα ως όρισμα σε μία συνάρτηση, δίνεις το όνομά του απλώς, χωρίς να ορίζεις αριθμό κελιών ή κάτι τέτοιο. Στην πράξη, για το forward declaration μίας συνάρτησης:

 

>int function(int array[], int size);

το παραπάνω είναι ισοδύναμo με αυτό:

 

>int function(int *array, int size);

 

όπως και με αυτό:

>int function(int*, int);

και σημαίνει «η συνάρτηση δέχεται ως πρώτο όρισμα έναν pointer προς διεύθυνση μνήμης όπου αποθηκεύεται πληροφορία τύπου int».

 

 

Όταν την καλείς, για να περάσεις ολόκληρο τον πίνακα, αρκεί να περάσεις τη διεύθυνση μνήμης του πρώτου στοιχείου του πίνακα:

 

>int array[4] = {1, 2, 3, 4};
int size = 4;

variable = function(array, size);

 

το οποίο είναι ισοδύναμο με αυτό:

>variable = function(&array[0], size);

 

...όπως πιθανόν να έχεις δει στην αριθμητική δεικτών.

Δημοσ.
Ωραία. Αν θέλεις να περάσεις ολόκληρο τον πίνακα ως όρισμα σε μία συνάρτηση, δίνεις το όνομά του απλώς, χωρίς να ορίζεις αριθμό κελιών ή κάτι τέτοιο. Στην πράξη, για το forward declaration μίας συνάρτησης:

 

>int function(int array[], int size);

το παραπάνω είναι ισοδύναμo με αυτό:

 

>int function(int *array, int size);

 

όπως και με αυτό:

>int function(int*, int);

και σημαίνει «η συνάρτηση δέχεται ως πρώτο όρισμα έναν pointer προς διεύθυνση μνήμης όπου αποθηκεύεται πληροφορία τύπου int».

 

 

Όταν την καλείς, για να περάσεις ολόκληρο τον πίνακα, αρκεί να περάσεις τη διεύθυνση μνήμης του πρώτου στοιχείου του πίνακα:

 

>int array[4] = {1, 2, 3, 4};
int size = 4;

variable = function(array, size);

 

το οποίο είναι ισοδύναμο με αυτό:

>variable = function(&array[0], size);

 

...όπως πιθανόν να έχεις δει στην αριθμητική δεικτών.

 

Καλά τα λες όλα αλλά είναι άραγε σωστό να λέμε ότι:

 

function(int *array, int sz);

 

είναι το ίδιο με

 

function(int array[], int sz);

 

Οι πίνακες δεν είναι δείκτες μην τα συγχέουμε...

Δημοσ.

Έχεις δίκιο, φυσικά και δεν ισχύει πίνακας = δείκτης. Στο παράδειγμα με το πρωτότυπο όμως, μόνο σημασιολογικά δεν είναι το ίδιο. Και στη μία και στην άλλη περίπτωση, αυτό που περιμένει να δει η συνάρτηση είναι διεύθυνση μνήμης όπου υπάρχει δεδομένο int τύπου...

Δημοσ.
Καλά τα λες όλα αλλά είναι άραγε σωστό να λέμε ότι:

 

function(int *array, int sz);

 

είναι το ίδιο με

 

function(int array[], int sz);

 

Οι πίνακες δεν είναι δείκτες μην τα συγχέουμε...

Απ'ό,τι ξέρω (δηλαδή διάφορα "πειράματα" που έχω κάνει ο ίδιος) έχω καταλάβει πως π.χ. μια int[] array είναι απλώς ένας pointer σε μια σειρά από ints. Οπότε *x είναι ίδιο με x[0], *(x+1) είναι ίδιο με x[1] κ.ο.κ., όπου x είναι είτε array είτε pointer. Οπότε ναι, πιστεύω πως είναι ίδια.

Διορθώστε με αν κάνω λάθος.

Edit ~ Μόλις είδα το post του parsifal, δεν κατάλαβα πως ήταν σημασιολογικά... Nvm me.

Δημοσ.

Υπάρχει μία παγίδα στο να σκέπτεται ο προγραμματιστής γενικώς κάθε array ως pointer και αυτό μάλλον είχε στο μυαλό του ο bokarinho.

 

1. Έστω στατικός πίνακας int και ένας int pointer:

 

>
int array[2];
int *p;

 

Μπορεί ως έκφραση, το array σκέτο να αποτιμάται στη διεύθυνση μνήμης του πρώτου στοιχείου του πίνακά μας, αλλά το array καθεαυτό δεν είναι modifiable object. Π.χ. αυτό δεν επιτρέπεται:

>
array = p;

 

Νομίζω στη βιβλιογραφία, η έκφραση array εδώ αναφέρεται ως "unmodifiable lvalue", κι έτσι είναι στην πράξη. Λειτουργεί ως constant.

 

 

2. Μία συνάρτηση όπως η παραπάνω του φίλου ColdFusion, δε θα είχε νόημα να κληθεί με παράμετρο κάτι άλλο πλην του ονόματος ενός στατικού πίνακα ή ενός pointer προς δυναμικά δεσμευμένο μπλοκ μνήμης. Π.χ. ένας pointer στον οποίο δεν έχουμε δώσει ακόμη τιμή. Και κακώς έγραψα:

και σημαίνει «η συνάρτηση δέχεται ως πρώτο όρισμα έναν pointer προς διεύθυνση μνήμης όπου αποθηκεύεται πληροφορία τύπου int».

 

Το σωστό είναι «η συνάρτηση δέχεται ως πρώτο όρισμα διεύθυνση μνήμης όπου αποθηκεύεται πληροφορία τύπου int». Τώρα, αν θα τη δώσεις με pointer ή με το όνομα ενός stored object δε θα κάνει καμμία διαφορά για αυτό που θα λάβει τελικά η συνάρτηση.

Δημοσ.
Υπάρχει μία παγίδα στο να σκέπτεται ο προγραμματιστής γενικώς κάθε array ως pointer και αυτό μάλλον είχε στο μυαλό του ο bokarinho.

 

1. Έστω στατικός πίνακας int και ένας int pointer:

 

>
int array[2];
int *p;

 

Μπορεί ως έκφραση, το array σκέτο να αποτιμάται στη διεύθυνση μνήμης του πρώτου στοιχείου του πίνακά μας, αλλά το array καθεαυτό δεν είναι modifiable object. Π.χ. αυτό δεν επιτρέπεται:

>
array = p;

 

Νομίζω στη βιβλιογραφία, η έκφραση array εδώ αναφέρεται ως "unmodifiable lvalue", κι έτσι είναι στην πράξη. Λειτουργεί ως constant.

 

 

2. Μία συνάρτηση όπως η παραπάνω του φίλου ColdFusion, δε θα είχε νόημα να κληθεί με παράμετρο κάτι άλλο πλην του ονόματος ενός στατικού πίνακα ή ενός pointer προς δυναμικά δεσμευμένο μπλοκ μνήμης. Π.χ. ένας pointer στον οποίο δεν έχουμε δώσει ακόμη τιμή. Και κακώς έγραψα:

 

 

Το σωστό είναι «η συνάρτηση δέχεται ως πρώτο όρισμα διεύθυνση μνήμης όπου αποθηκεύεται πληροφορία τύπου int». Τώρα, αν θα τη δώσεις με pointer ή με το όνομα ενός stored object δε θα κάνει καμμία διαφορά για αυτό που θα λάβει τελικά η συνάρτηση.

 

Σωστός....Δεν έχω να πω κουβέντα. Επίσης να μην τα μπλέκουμε, το γενικό δόγμα ότι οι δείκτες είναι πίνακες. Αν έχουμε ένα πίνακα:

 

int nArray[10];

 

και

 

int *nArray;

 

Τότε αυτό το πρόγραμμα τι μας δείχνει;

 

>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
int nArray[10];
int *ptrArray;
printf("nArray:%d\nptrToArray:%d\n", sizeof(nArray), sizeof(ptrArray));
getchar();
return 0;
}

 

Τυπώνει:

 

nArray:40

ptrToArray:4

 

Οπότε προσοχή γιατί ο δείκτης είναι δείκτης δεν είναι πίνακας.

Δημοσ.
Σωστός....Δεν έχω να πω κουβέντα. Επίσης να μην τα μπλέκουμε, το γενικό δόγμα ότι οι δείκτες είναι πίνακες. Αν έχουμε ένα πίνακα:

 

int nArray[10];

 

και

 

int *nArray;

 

Τότε αυτό το πρόγραμμα τι μας δείχνει;

 

>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
int nArray[10];
int *ptrArray;
printf("nArray:%d\nptrToArray:%d\n", sizeof(nArray), sizeof(ptrArray));
getchar();
return 0;
}

 

Τυπώνει:

 

nArray:40

ptrToArray:4

 

Οπότε προσοχή γιατί ο δείκτης είναι δείκτης δεν είναι πίνακας.

 

Κάτι που όμως δεν χρειάζεται αναφορά επείδη το πρώτο πράγμα που μαθαίνει κάποιος οσο αφορά τους δείκτες είναι ότι δεν αποθηκεύουν τιμές αλλά διευθύνσεις. Και σε ένα 32-Bit λειτουργικό σύστημα το μέγεθος τους είναι 4 bytes. :-D

Δημοσ.
Κάτι που όμως δεν χρειάζεται αναφορά επείδη το πρώτο πράγμα που μαθαίνει κάποιος οσο αφορά τους δείκτες είναι ότι δεν αποθηκεύουν τιμές αλλά διευθύνσεις. Και σε ένα 32-Bit λειτουργικό σύστημα το μέγεθος τους είναι 4 bytes. :-D

υπ'όψη οτι και η διεύθυνση μνήμης είναι μια τιμή (συνήθως 16αδικός αριθμός)

Αρχειοθετημένο

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

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