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

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

Δημοσ.

Ναι.

 

Καταρχην ενα ωραιο "κολπο" να ξεφυγεις απο ολη αυτη την σπαζοκεφαλια για μενα παντα ειναι να πεις....

 

στην Σελ. 269 στον King εκει που κανει την απλοποιηση απο p = &a[0] σε p = a συμβαινει αυτο επειδη δινουν την ιδια αριθμητικη τιμη δηλαδη την ιδια διευθυνση. Τελος

 

>

#include <stdio.h>

int main( void )
{

int a[1][2] = { {1 , 3}} , x=1 , (*p)[2] , **q , b[2];

printf(" %d\n" , **a);

if ( a[0] == &a[0][0])
puts(" a[0] is equivalent with &a[0][0]");

if( a == &a[0])
puts("a is equivalent with a[0]");

printf(" Results of two-dimensional : %p , %p , %p , %p \n" , &a[0] , a , &a , a[0] );

printf(" Results of one-dimensional : %p , %p , %p " , &b , b , &b[0]);

//p = q;

//p = &x;

//printf(" %d " , *p);

return 0;
}

 

Διπλος δεικτης οντως δεν ειναι γιατι δεν μπορει να αρχικοποιηθει με q.

 

Μπορει πανευκολα καποιος να μπερδευτει ... ακομη και αν εχει διαβασει το προτυπο.... αν ξεχασει για λιγο οτι το a[0] ειναι πινακας και τον θεωρησει σαν στοιχειο :/

 

+ οτι ετσι οπως το γραφει ο King a is not a pointer to a[0][0] ; instead is a pointer to a[0] .

Το θεωρεις σαν δεικτη σε δεικτη. Και αρα λες ειναι διπλος και αλλο ενα βιβλιο που εχω το γραφει ετσι

και λεει οτι μπορεις να χρησιμοποιησεις και τον ** για το 1ο στοιχειο παντα.

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

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

Δημοσ.

+ οτι ετσι οπως το γραφει ο King a is not a pointer to a[0][0] ; instead is a pointer to a[0] .

Το θεωρεις σαν δεικτη σε δεικτη. Και αρα λες ειναι διπλος και αλλο ενα βιβλιο που εχω το γραφει ετσι

και λεει οτι μπορεις να χρησιμοποιησεις και τον ** για το 1ο στοιχειο παντα.

 

Ίσα ίσα, δεν θα έπρεπε να το εκλάβει ότι δείχνει σε πίνακα μια και το a[0] είναι πίνακας ?

 

>
char a[3][5];

  30  31  32  33  34
 |-------------------|
 | 1 | 7 | 6 | 2 | 9 |
 |-------------------|
 | 2 | 8 | 2 | 3 | 5 |
 |-------------------|
 | 3 | 3 | 8 | 5 | 1 |
 |-------------------|
  40  41  42  43  44

  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44
 |-----------------------------------------------------------|
 | 1 | 7 | 6 | 2 | 9 | 2 | 8 | 2 | 3 | 5 | 3 | 3 | 8 | 5 | 1 |
 |-----------------------------------------------------------|

 

Ας υποθέσουμε ότι έχουμε τον παραπάνω πίνακα και ότι έχει δεσμευτεί για αυτόν μνήμη από το 30 μέχρι το 44. Η φράση "a" είναι συμβολικό όνομα και σημαίνει την διεύθυνση 30. Αυτή η διεύθυνση είναι γνωστή και μπαίνει όπου έχουμε a σε αντίθεση με ένα δείκτη που πρέπει να διαβαστεί η "τιμή" του. Το δεύτερο σχηματικό δείχνει για ευκολία πως είναι ο πίνακας στη μνήμη.

 

>
char (*p1)[5];
p1 = a;

  135
 |----|
p1| 30 |
 |----|

(*p1)[2] = 3;

 

Ορίζουμε τον p1 που είναι δείκτης σε πίνακα 5 στοιχείων και έπειτα του θέτουμε ως τιμή την διεύθυνση της 1ης γραμμής. Δηλαδή στη μνήμη έχει δεσμευτεί η διεύθυνση 135 για τον δείκτη και ως τιμή γράφεται το 30 που είναι η διεύθυνση της 1ης γραμμής. Όταν κάνουμε dereference τον παραπάνω δείκτη διαβάζεται η τιμή 30 και χρησιμοποιείται σαν διεύθυνση. Αυτό που προκύπτει είναι, σύμφωνα με τη δήλωση του p1, πίνακας. Μετά θέτουμε την τιμή 3 στο 3ο στοιχείο της γραμμής. Αυτό γίνεται με τον τρόπο που γίνεται στους πίνακες δηλαδή αφού έχει γίνει το στάδιο του dereference, η τιμή του 1ου στοιχείου του πίνακα *p1 είναι γνωστή και απλά προστίθεται όσο πρέπει για να φτάσουμε στο 3ο στοιχείο δηλαδή θα γράψουμε στη διεύθυνση 30 + 2*1 = 32 την τιμή 3.

 

>
char **p2;
p2 = a;

  261
 |----|
p2| 30 |
 |----|

**p2 = 4;

 

Εδώ ορίζουμε τον p2 σαν δείκτη σε δείκτη σε char και του θέτουμε ως τιμή και πάλι τη διεύθυνση της 1ης γραμμής. Αυτή τη φορά έχει δεσμευτεί η διεύθυνση 261 για τον δείκτη και ως τιμή γράφεται και πάλι το 30 που είναι η διεύθυνση της 1ης γραμμής. Όταν κάνουμε dereference τον παραπάνω δείκτη διαβάζεται η τιμή 30 και χρησιμοποιείται σαν διεύθυνση. Αυτό που προκύπτει (δηλαδή το *p2) είναι, σύμφωνα με τη δήλωση του p2, δείκτης. Όταν μετά πάμε να προσπελάσουμε το **p2, δεν θα γίνει η ίδια διαδικασία με το *p1 αλλά εφόσον προέκυψε δείκτης, θα διαβαστεί η τιμή της διεύθυνσης 30 η οποία είναι 1 και θα χρησιμοποιηθεί ως διεύθυνση. Οπότε την τιμή 4 θα πάει να την γράψει στη διεύθυνση 1 η οποία δεν ανήκει στο πρόγραμμά μας.

 

Οπότε έχουμε πως σε πίνακες είναι πάντα γνωστή η διεύθυνση του 1ου στοιχείου καθώς και οι διαστάσεις οπότε το Ν-ιοστό στοιχείο υπολογίζεται απλά προσθέτοντας το μέγεθος των στοιχείων στην γνωστή αυτή αρχική διεύθυνση. Αντίθετα στους δείκτες γίνεται dereference και χρησιμοποιείται η εκάστοτε τιμή ως διεύθυνση για κάθε επίπεδο δείκτη που έχουμε. Έτσι για μονοδιάστατους πίνακες οι δύο διαδικασίες συμπίπτουν και δουλεύουν σωστά αλλά _όχι_ για πολυδιάστατους.

  • Like 1
Δημοσ.

Οκ . Μια χαρα , ευχαριστω. :)

 

Να ρωτησω κατι τελευταιο , λεει οτι ο a δεν ειναι pointer στο a[0][0] ενω εχουν και τα τρια την ιδια διευθυνση δηλαδη το a[0][0] τι ειναι ακριβως? ενα απλο στοιχειο του συνολικου πινακα μας (το πρωτο στοιχειο στο ανθρωπινο μυαλο αλλα οχι και στην μνημη του υπολογιστη)... το a απλα ενα συμβολικο ονομα για τον συνολικο πινακα (πινακας πινάκων) και το a[0] απλα ο 1ος πινακας αυτων (γραμμη 0 ) για την row-order προσεγγιση της C

 

Εκεινο που διαφερει απο οσο ειδα ειναι η τιμη που δινει ο sizeof αν τον εφαρμοσεις και στα τρια αυτα διαφορετικα....

Δημοσ.

@imitheos:

 

Ίσως σε παρερμήνευσα, απλώς ήθελα να τονίσω πως και οι διπλοί πίνακες μπορούν σε ορισμένες περιπτώσεις να διαχειριστούν ως διπλοί δείκτες, έστω κι αν σε ANSI C και μετά χρειάζεται casting, ώστε να μην βγάζουν warning οι compilers (εγώ δεν είχα χρησιμοποιήσει casting στα παραδείγματα που πόσταρα, απλώς αγνόησα τα warnings).

Δημοσ.

Καλησπέρα. Μια ασκηση ζητάει να ξαναγραφει η παρακατω συνάρτηση ωστε να χρησιμοποιει αριθμητικη δεικτών αντι του array indexing καθως και την εξάλειψη των i , j μεταβλητών και του τελεστή [] . Να χρησιμοποιηθεί ενα loop αντι ενος εμφωλιασμένου.

 

Ο τρέχων κώδικας

 

>

int sum_two_dimensional_array ( const int a[][LEN] , int n )
{
int i , j , sum = 0

for (i = 0; i < n ; i++)
for ( j = 0; j < LEN; j++)
sum += a[i][j];
return sum;
}

 

Έχω γράψει αυτο αλλα δεν με ικανοποιει :

 

>

#include <stdio.h>
int sum_two_dimensional_array(int [][3] , int );

int main( void )
{
int arr2d[2][3] = { { 10 , 20 , 30 } , { 40 , 50 , 60} } ;

printf(" Sum is : %d " , sum_two_dimensional_array(arr2d , 3) );

return 0;
}

int sum_two_dimensional_array(int arr2d[][3] , int n)
{
int sum=0 , i = 0;
int *p ;

while ( i < 2)
{

for( p = arr2d[i] ; p < arr2d[i] + n ; p++)
sum+= *p;

++i;
}
return sum;

}

 

Καταρχην χρησιμοποιει μεταβλητη i και επισης δεν ειναι VLA... νομιζω στα VLA αν οι διαστασεις δεν ειναι ισες τοτε έχουμε ακαθοριστη συμπεριφορα. Εχει κανεις να προτεινει καποιον καλυτερο κώδικα για το παραπανω ζητημα? Εχει νοημα να χρησιμοποιησεις VLA εδω ? ή ειναι απλα μια ασκησουλα που μπορεις να παρακαμψεις απλα με εναν εξαρχης αρχικοποιημενο πινακα στανταρ στοιχειων.

 

Επισης σε μια αλλη ασκηση οπως η παραπανω ζητα να γινει το ιδιο αλλα με μονοδιαστατο πίνακα οποτε ενας κωδικας ενδεικτικος μπορει να ειναι :

 

>


#include <stdio.h>
int sum_array(int * , int );

int main( void )
{
int n , i=0 ;

do
{
printf(" Give a valid number of elements : ");
scanf("%d" , &n);
} while ( n < 2 );

int arr[n];

printf(" Give the elements > ");

for( ; i<n; i++)
scanf("%d" , (arr + i) );

printf(" Sum is : %d " , sum_array(arr , n) );

return 0;
}
int sum_array(int *arr , int n)
{
int sum=0 , *p;

for( p = arr ; p < arr + n ; p++)
sum+= *p;

return sum;

}

 

Εδω δεν μ αρεσει που ο King βαζει μεσα το const int ..... μου δινει προειδοποιηση ο μεταγλωτιστης ετσι οπως το εχει ο King εδω

http://knking.com/books/c2/answers/c12.html

 

επισης

 

γιατι χρησιμοποιει

 

>
const int a[] 

 

μεσα στις δηλωσεις εφοσον θελει να εξαλειψει καποιος ολες τις εμφανισεις του τελεστη [].

Δημοσ.

Με ένα λουπ

>
for(i=0; i < n*LEN; i++)
sum += *( *(a + i/LEN)+ i%LEN);

 

Πιστευω τώρα ειναι εντάξει.... αν και δεν θα τον δηλωσω σαν const int τον πινακα... δεν βρισκω νοημα.

Δεν εχω σκεφτει πολυ γιατι ο King το βάζει ετσι και στην παραπανω περιπτωση που εχω ποσταρει για αυτο και το ποσταρισα εδω αν εχει κανεις ορεξη και ειναι σημαντικο να το συζητησουμε... αλλωστε στην λυση που δινει διαμαρτυρεται ο compiler... οποτε πρεπει να κάνεις και τον δεικτη const int.

 

>

#include <stdio.h>
#define LEN 3
int sum_two_dimensional_array(int [][LEN]);

int main( void )
{
int arr2d[2][3] = { { 10 , 20 , 30 } , { 40 , 50 , 60} };

printf(" Sum is : %d " , sum_two_dimensional_array(arr2d));

return 0;
}

int sum_two_dimensional_array(int arr2d[][LEN])
{
int *p , sum=0 ;

 for( p = &arr2d[0][0] ; p <= &arr2d[1][2]; p++)
		 sum+= *p;

return sum;

}

Δημοσ.

 

 

Πιστευω τώρα ειναι εντάξει.... αν και δεν θα τον δηλωσω σαν const int τον πινακα... δεν βρισκω νοημα.

Δεν εχω σκεφτει πολυ γιατι ο King το βάζει ετσι και στην παραπανω περιπτωση που εχω ποσταρει για αυτο και το ποσταρισα εδω αν εχει κανεις ορεξη και ειναι σημαντικο να το συζητησουμε... αλλωστε στην λυση που δινει διαμαρτυρεται ο compiler... οποτε πρεπει να κάνεις και τον δεικτη const int.

 

>
int sum_two_dimensional_array(int arr2d[][LEN])
{
int *p , sum=0 ;

    for( p = &arr2d[0][0] ; p <= &arr2d[1][2]; p++)
            sum+= *p;

return sum;

}

 

Η συμπεριφορά του δεν είναι ίδια με αυτού που έγραψε ο albNik. Αν και θα παίξει παντού, το δικό σου τυπικά δεν είναι σωστό.

 

>
#include <stdio.h>

#define ROWS 2
#define COLS 3

int sum_two_dimensional_array(int[][COLS], int);

int main(void)
{
   int arr2d[2][3] = { {10, 20, 30}, {40, 50, 60} };

   printf("Sum is : %d\n", sum_two_dimensional_array(arr2d, ROWS * COLS));

   return 0;
}

int sum_two_dimensional_array(int arr2d[][COLS], int n)
{
   int sum = 0;
   int *p;
   unsigned char *c;


   c = (unsigned char *)arr2d;
   while (n > 0) {
       p = (int *)c;
       sum += *p;
       c += sizeof(int);
       n--;
   }
   return sum;
}

 

Χρησιμοποιεί αριθμητική δεικτών, ένα loop, δεν χρησιμοποιεί [] ούτε i, j αλλά μόνο το υπάρχον n.

Δημοσ.

imitheos, νομίζω πως αυτό που έγραψες θα τρέξει μόνο εάν δηλωθεί ο πίνακας όπως τον έχεις δηλώσει. Σε περίπτωση που δηλωθούν δυναμικά οι γραμμές του, τότε νομίζω πως δεν τα τρέξει.

Δημοσ.

imitheos, νομίζω πως αυτό που έγραψες θα τρέξει μόνο εάν δηλωθεί ο πίνακας όπως τον έχεις δηλώσει. Σε περίπτωση που δηλωθούν δυναμικά οι γραμμές του, τότε νομίζω πως δεν τα τρέξει.

 

Την δήλωση την πήρα όπως την έδωσε ο star_light (που την πήρε όπως την έδωσε ο king). Δυναμικά εννοείς με malloc κάποιων int * και μετά πάλι malloc σε κάθε "γραμμή" ?

Δημοσ.

Γραφω C στον eclipse με minGW

Γιατι τις περισσοτερες φορες δεν μου βγαζει τα ερορς παρα πεταει μια καρτα που λεει οτι το αρχειο projectname.exe σταματησε να λειτουργει;;;Πως θα το κανω να βγαζει τα ερορς?

Δημοσ.

Καλησπέρα. Μια ασκηση ζητάει να ξαναγραφει η παρακατω συνάρτηση ωστε να χρησιμοποιει αριθμητικη δεικτών αντι του array indexing καθως και την εξάλειψη των i , j μεταβλητών και του τελεστή [] . Να χρησιμοποιηθεί ενα loop αντι ενος εμφωλιασμένου.

 

Ο τρέχων κώδικας

 

 

>

int sum_two_dimensional_array ( const int a[][LEN] , int n )
{
int i , j , sum = 0

for (i = 0; i < n ; i++)
for ( j = 0; j < LEN; j++)
sum += a[i][j];
return sum;
}

 

 

 

Έχω γράψει αυτο αλλα δεν με ικανοποιει :

 

 

>

#include <stdio.h>
int sum_two_dimensional_array(int [][3] , int );

int main( void )
{
int arr2d[2][3] = { { 10 , 20 , 30 } , { 40 , 50 , 60} } ;

printf(" Sum is : %d " , sum_two_dimensional_array(arr2d , 3) );

return 0;
}

int sum_two_dimensional_array(int arr2d[][3] , int n)
{
int sum=0 , i = 0;
int *p ;

while ( i < 2)
{

for( p = arr2d[i] ; p < arr2d[i] + n ; p++)
sum+= *p;

++i;
}
return sum;

}

 

 

Καταρχην χρησιμοποιει μεταβλητη i και επισης δεν ειναι VLA... νομιζω στα VLA αν οι διαστασεις δεν ειναι ισες τοτε έχουμε ακαθοριστη συμπεριφορα. Εχει κανεις να προτεινει καποιον καλυτερο κώδικα για το παραπανω ζητημα? Εχει νοημα να χρησιμοποιησεις VLA εδω ? ή ειναι απλα μια ασκησουλα που μπορεις να παρακαμψεις απλα με εναν εξαρχης αρχικοποιημενο πινακα στανταρ στοιχειων.

 

Όχι μόνο δεν χρειάζεται VLA εδώ, αλλά είναι κι ελάχιστες οι περιπτώσεις που χρειάζεται να χρησιμοποιήσει κανείς VLA γενικώς (παρόλο που ξέρω πως σου αρέσουν :P). Η γνώμη μου είναι να τους διαγράψεις από το λεξιλόγιό σου και να τους αντικαταστήσεις με...

 

>
whatever *arr = malloc()/calloc();
...
free( arr );

 

Από εκεί και πέρα, μια εναλλακτική υλοποίηση χωρίς καθόλου counters και [] θα μπορούσε π.χ. να είναι και κάπως έτσι...

 

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

#define NROWS	2
#define NCOLS	3

/* --------------------------------------------------
*
* --------------------------------------------------
*/
int arr2d_sumElements( int arr2d[][NCOLS], int nrows )
{
   int sum = 0;

   // sanity check
   if ( !arr2d || nrows < 1 )
       return INT_MIN;

   // actual calc
   for (int *walk = (int *)arr2d; walk < ((int *)arr2d + nrows * NCOLS); walk++)
       sum += *walk;

   return sum;
}

/* --------------------------------------------------
*
* --------------------------------------------------
*/
int main( void )
{
int arr2d[NROWS][NCOLS] = { {10, 20, 30}, {40, 50, 60} };

arr2d_print( arr2d, NROWS );
printf( "sum: %d\n", arr2d_sumElements(arr2d, NROWS) );

exit( EXIT_SUCCESS );
}

 

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

 

>
int arr2d_sumElements( int arr2d[][NCOLS], int nrows )
{
   int sum = 0;

   // sanity check
   if ( !arr2d || nrows < 1 )
       return INT_MIN;

   // actual calc
   int *walk = (int *)arr2d;            // address of arr2d's 1st int element
   int *stop = ((int *)arr2d + nrows * NCOLS);    // address of arr2d's last int element

   while ( walk < stop )
       sum += *walk++;

   return sum;
}

 

ΥΓ1. Ίσως να μου 'χει ξεφύγει τίποτα, οπότε... take the code with a pinch of salt (που λένε κι οι Αγγλόφωνοι :lol:)

 

ΥΓ2. To code-tag πράγματι σπάει καρύδια.

Δημοσ.

Αυτό έγραψε και ο starlight αλλά όχι τόσο όμορφα όσο εσύ. Πρακτικά είπαμε ότι θα παίξει παντού αλλά τυπικά δεν μπορείς να κάνεις "walk" ένα δισδιάστατο πίνακα έτσι (σαν μονοδιάστατο δηλαδή) παρά μόνο με char όπως έδειξα πριν.

Δημοσ.

Αυτό έγραψε και ο starlight αλλά όχι τόσο όμορφα όσο εσύ. Πρακτικά είπαμε ότι θα παίξει παντού αλλά τυπικά δεν μπορείς να κάνεις "walk" ένα δισδιάστατο πίνακα έτσι (σαν μονοδιάστατο δηλαδή) παρά μόνο με char όπως έδειξα πριν.

 

Γιατί μπορείς μόνο με char;

 

ΥΓ. Δεν είναι εριστική η ερώτησή μου, απορία είναι.

 

 

Δημοσ.

Γραφω C στον eclipse με minGW

Γιατι τις περισσοτερες φορες δεν μου βγαζει τα ερορς παρα πεταει μια καρτα που λεει οτι το αρχειο projectname.exe σταματησε να λειτουργει;;;Πως θα το κανω να βγαζει τα ερορς?

 

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

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

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