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

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

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

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

Δημοσ.

Καλησπέρα. Βασικα εχω το εξης θεματάκι (το οποιο δεν έχω προλαβει να το ψάξω πολυ μονος μου)

Ε ψάξε το πρώτα μόνος σου και μετά ρωτάς :)

 

> 
#define [b]len[/b] 10

int array_max(int array[[b]len[/b]] , int [b]len[/b])

> tests2.c:57: error: expected ‘;’, ‘,’ or ‘)’ before numeric constant 
tests2.c:83: warning: implicit declaration of function ‘array_max’

Για το πρώτο σκέψου πως γίνεται η δήλωση της συνάρτησης αφού την περιλάβει ο preprocessor. Για το δεύτερο διάβασε για function prototypes. (Edit: grrr. Κάτι κάνω λάθος και ποτέ δεν παίζει σωστά το bold)

 

>
result = sum_array((int [b]a[/b][]) {0,1,2} , 3);

> tests.c:19: error: expected ‘)’ before ‘a’

Μην βάζεις "πολύπλοκα" πράγματα αν δεν τα έχεις καταλάβει.

EXAMPLE 1

int *p = (int []){2, 4};

Hint: Χωρίς "a"

Δημοσ.

...

Edit: grrr. Κάτι κάνω λάθος και ποτέ δεν παίζει σωστά το bold)

Μέσα σε code tags δεν παίζουν τα υπόλοιπα formatting tags.

 

Μην βάζεις "πολύπλοκα" πράγματα αν δεν τα έχεις καταλάβει.

+ πολλά!

Δημοσ.

Σιγα το πολυπλοκο!!!!!!

 

Αν και ο migf1 ξερει πολυ καλα οτι μου αρεσει το πολυπλοκο :D

 

Στραβομάρα δεν είδα οτι δεν θέλει a

 

> result = sum_array((int []) {0,1,2} , 3); 

 

οποτε έχεις έναν πίνακα που φτιάχνεις επιτόπου για τις ανάγκες της κλήσης σου με στοιχεία 0,1,2

και το αποτελεσμα της συνάρτησης που επιστρέφεται δίνεται στην μεταβλητή result!!! Ειναι ωραιο κολπο αν δεν έχεις να χρησιμοποιησεις καπου αλλου στην main τον συγκεκριμένο.

 

Ευχαριστω !

 

btw δεν ξερω αν έχει να κάνει με τον δικο μου compiler αλλα

τα Versions της 199 2b & 3b για την δήλωση δεν μου δουλεύουν...

 

πχ

> int array_max( int  , int []) 

Δημοσ.

btw δεν ξερω αν έχει να κάνει με τον δικο μου compiler αλλα

τα Versions της 199 2b & 3b για την δήλωση δεν μου δουλεύουν...

 

πχ

> int array_max( int  , int []) 

Έτσι που το διατύπωσες άργησα λίγο να το πιάσω. Εννοείς τις δηλώσεις της συνάρτησης sum_array που δίνει ο King στη σελίδα 199 ? Αν ναι, πρόσεξες ότι υπάρχει ερωτηματικό στο τέλος της δήλωσης ?

 

Στη δήλωση του prototype μιας συνάρτησης μπορούμε να παραλείψουμε τα ονόματα και απλά να υπάρχουν οι τύποι. Αυτό όμως γίνεται μόνο στο prototype. πχ

 

>
#include <stdio.h>

int sum_array(int, int []); /* Ginetai kai xwris onomata */

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

printf("Sum is %d\n", sum_array(5, a));

return 0;
}

int sum_array(int n, int a[]) /* Kanonika me onomata */
{
int sum = 0;

while (n --> 0)
	sum += a[n];

return sum;
}

Δημοσ.

@imithee σωστός.

 

δήλωση μιας συνάρτησης != Ορισμός μιας συνάρτησης.

 

Να ρωτησω κατι τελευταιο (εχω και πολλες καμια φορα :P )

 

Σε μια δηλωση της μορφης :

 

> func(int n , int a[] ); 

 

Ο compiler δεν θα έπρεπε να κτυπάει επειδη δεν βρίσκει το μέγεθος του πίνακα?

Δημοσ.

Με το απλό σκεπτικό μου θα πω όχι. Γιατί στην ουσία οι πίνακες είναι απλά δείκτες στην c. Οπότε (λογικά) ο compiler βλέπει έναν δείκτη εκεί που είναι ο πίνακας.

 

Δηλαδή

>func(int n , int* a );

Δημοσ.

Με το απλό σκεπτικό μου θα πω όχι. Γιατί στην ουσία οι πίνακες είναι απλά δείκτες στην c. Οπότε (λογικά) ο compiler βλέπει έναν δείκτη εκεί που είναι ο πίνακας.

 

Δηλαδή

>func(int n , int* a );

 

Ναι οκ. Συμφωνω αλλα αυτο

δεν μπορω να το κανω στην main()

 

>
int main( void )
{
int a[];

      return 0;
}

 

Κτυπαει οτι ξέχασα το μέγεθος :P

Δημοσ.

Ναι οκ. Συμφωνω αλλα αυτο

δεν μπορω να το κανω στην main()

 

>
int main( void )
{
int a[];

  	return 0;
}

 

Κτυπαει οτι ξέχασα το μέγεθος :P

 

Χτυπαει επειδη δεν υπαρχει τετοια δηλωση.

Δημοσ.

Χτυπαει επειδη δεν υπαρχει τετοια δηλωση.

 

Τελοςπαντων εφοσον δεν προκειται να το χρησιμοποιησω ποτε

δεν θα κατσω να πονοκεφαλιαστώ με δαύτο.

 

Αν χρειαστεί βάζουμε στον ορισμο της συνάρτησης τις παραμετρους

με τα ονοματα και τελειωσε η υποθεση ειναι και πιο ευαναγνωστο

μιας και δειχνει άμεση συνδεση του μηκους του πινακα με την 2η παραμετρο

. -.-

 

Ευχαριστω παντως.

Δημοσ.

...

Κτυπαει οτι ξέχασα το μέγεθος :P

Ξαναδιάβασε την ενότητα/κεφάλαιο που μιλάει για το τι είναι ορισμός (definition) και τι δήλωση (deceleration) γιατί από ότι φαίνεται τα συγχέεις.

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

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

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

Σε μια δηλωση της μορφης :

 

> func(int n , int a[] ); 

 

Ο compiler δεν θα έπρεπε να κτυπάει επειδη δεν βρίσκει το μέγεθος του πίνακα?

Με το απλό σκεπτικό μου θα πω όχι. Γιατί στην ουσία οι πίνακες είναι απλά δείκτες στην c. Οπότε (λογικά) ο compiler βλέπει έναν δείκτη εκεί που είναι ο πίνακας.

 

Δηλαδή

>func(int n , int* a );

Ναι οκ. Συμφωνω αλλα αυτο

δεν μπορω να το κανω στην main()

 

>
int main( void )
{
int a[];

      return 0;
}

 

Κτυπαει οτι ξέχασα το μέγεθος :P

 

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

 

Για να είμαστε πιο τυπικοί/σωστοί, οι πίνακες _δεν_ είναι δείκτες και οι δείκτες _δεν_ είναι πίνακες. Πολλές φορές και σε σοβαρά βιβλία ακόμη διαβάζουμε "οι πίνακες είναι δείκτες", "οι πίνακες ισοδυναμούν με δείκτες" και άλλα τέτοια. Όλες αυτές οι διατυπώσεις είναι λανθασμένες. Είναι σχεδόν βέβαιο ότι και εγώ θα το διατυπώσω λάθος :) αλλά θα προσπαθήσω μήπως και το πω σωστά.

 

>
char a[] = "mitsos";
char *p = "kotsos";

>
   31  32  33  34  35  36  37
  +---+---+---+---+---+---+---+
a: | m | i | t | s | o | s | 0 |
  +---+---+---+---+---+---+---+
   40         51  52  53  54  55  56  57
  +----+     +---+---+---+---+---+---+---+
p: | 51 | ==> | k | o | t | s | o | s | 0 |
  +----+     +---+---+---+---+---+---+---+

 

Όταν δηλώνεις ένα πίνακα με n στοιχεία, δεσμεύεται τόση συνεχόμενη μνήμη όση χρειάζονται για αυτά. Με τον δείκτη δεσμεύεται μνήμη όσο χρειάζεται για δείκτη και μετά απλά δείχνει κάπου. Αν θέλεις να χρησιμοποιήσεις το δείκτη θα πρέπει εσύ να εκχωρήσεις μνήμη με την malloc ή να τον κάνεις να δείχνει κάπου όπως στο παραπάνω παράδειγμα.

 

>
p++; /* δείχνει στο 'o' */
a++; /* λάθος */

Μια άλλη διαφορά είναι η παραπάνω. Ενώ ένας δείκτης μπορεί να αλλάξει ώστε να δείχνει σε άλλη θέση, ένας πίνακας δεν μπορεί να αλλάξει. Αυτό δημιούργησε ένα άλλο όρο "οι πίνακες είναι σταθεροί δείκτες" ο οποίος επίσης δεν είναι 100% σωστός.

 

Ας έλθουμε τώρα στο θέμα του "πίνακας σε δήλωση συνάρτησης". Το πρότυπο αναφέρει.

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 και &, τότε αυτή μετατρέπεται σε δείκτη στο πρώτο στοιχείο.

>
int a[5];
1)int *p = a;
2)int *p = &a[0];

Όταν δηλαδή γράφουμε το 1 είναι σαν να γράψαμε το 2. Για αυτό το λόγο η συνάρτηση βλέπει ένα δείκτη όπως είπε ο κομπιουτεράς και έτσι μπορείς να έχεις δηλώσεις τύπου a[].

 

Στους τελεστές sizeof και & οι πίνακες δεν μετατρέπονται. Ενώ η έκφραση sizeof(p) θα δώσει 8 σε 64bit, η sizeof(a) δεν θα δώσει 8 αλλά 20 γιατί το μέγεθος του πίνακα είναι 5 int * 4 μέγεθος.

>
int **q = &a;

Ομοίως, το παραπάνω δίνει "initialization from incompatible pointer type".

 

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

 

Παίρνω αφορμή από το σχόλιο του Chris6 για να τονίσω κάτι που παρέλειψα πριν. Γιατί ο Chris6 ανέφερε "την πρώτη διάσταση" άραγε ? Όπως διαβάσαμε στην παράγραφο του προτύπου, το "array of type" μετατρέπεται σε "pointer to type" οπότε η μετατροπή γίνεται μόνο μια φορά.

 

Έτσι όταν έχουμε int a[5][3] δηλώνουμε ένα πίνακα με στοιχεία 5 πίνακες με στοιχεία 3 ακεραίους. Έτσι η μετατροπή θα γίνει σε "δείκτης σε πίνακα με στοιχεία 3 ακεραίους" (και έτσι μπορείς να παραλείψεις την μία διάσταση) και _όχι_ σε "δείκτης σε δείκτη σε ακέραιο" ώστε να έχουμε int **a.

Δημοσ.

...

Για να είμαστε πιο τυπικοί/σωστοί, οι πίνακες _δεν_ είναι δείκτες και οι δείκτες _δεν_ είναι πίνακες. Πολλές φορές και σε σοβαρά βιβλία ακόμη διαβάζουμε "οι πίνακες είναι δείκτες", "οι πίνακες ισοδυναμούν με δείκτες" και άλλα τέτοια. Όλες αυτές οι διατυπώσεις είναι λανθασμένες. Είναι σχεδόν βέβαιο ότι και εγώ θα το διατυπώσω λάθος :) αλλά θα προσπαθήσω μήπως και το πω σωστά.

...

Οι πίνακες είναι δείκτες στο 1ο στοιχείο τους, αλλά με τον περιορισμό ότι δεν μπορούν να χρησιμοποιηθούν ως LVALUES. Σε αυτή τη φράση συνοψίζεται η ουσία.

Δημοσ.

Οι πίνακες είναι δείκτες στο 1ο στοιχείο τους, αλλά με τον περιορισμό ότι δεν μπορούν να χρησιμοποιηθούν ως LVALUES. Σε αυτή τη φράση συνοψίζεται η ουσία.

 

Δε θα το'λεγα. Δεικτης ειναι μια μεταβλητη που εχει μια virtual address που δειχνει καπου. Ο πινακας ειναι ενα "lable" (constant) που ουσιαστικα ειναι ενα offset που προσδιοριζει που βρισκεται ο πινκας σχετικα με την αρχη της stack.

εφοσον εχουμε

address = ebp - pin

δεν μπορουμε να πουμε οτι ο pin ειναι δεικτης

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

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