Κάτι αρκετά (έως πολύ) προχωρημένο: εναλλαγή δυο δεικτών ανεξαρτήτως τύπου. Το βασικό που πρέπει να σημειωθεί είναι πως εναλλάσσει τους δείκτες αυτούς κάθε αυτούς και όχι αυτά στα οποία δείχνουν οι δείκτες.
Αυτό στην πράξη σημαίνει πως για να εναλλάξετε π.χ. δυο πίνακες από int πρέπει πρώτα να βάλετε 2 δείκτες να δείχνουν στους πίνακες, να εναλλάξετε τους δείκτες και στη συνέχεια να αναφέρεστε στους πίνακες μέσω αυτών των δεικτών (και όχι μέσω των ονομάτων των πινάκων).
Το ίδιο ακριβώς πρέπει να κάνετε αν έχετε 2 strings δηλωμένα ως πίνακες από χαρακτήρες, π.χ.: char s1[256] = "string-1", char s2[256] = "string-2";
Αυτό συμβαίνει διότι ότι είναι δηλωμένο ως πίνακας, ναι μεν το όνομα του αντιστοιχεί σε δείκτη που δείχνει στο 1ο στοιχείο του πίνακα, αλλά δεν μπορεί να χρησιμοποιηθεί ως lvalue. Με άλλα λόγια, είναι read-only. Για αυτό χρειάζεται πρώτα να ορίσετε έναν νέο δείκτη να δείχνει κι αυτός στην αρχή του πίνακα, και μετά αυτόν μπορείτε να τον βάλετε να δείξει κάπου αλλού.
Αντίθετα, αν τον πίνακα αντί να τον δηλώσετε εξαρχής ως πίνακα (δηλαδή με αγκύλες) τον ορίσετε ως κανονικό δείκτη και τον κάνετε κατόπιν malloc() / calloc() τότε μπορείτε να τον διαχειριστείτε απευθείας. Σε αυτές τις περιπτώσεις δουλεύει κανονικά η εναλλαγή χωρίς να χρειάζονται έξτρα δείκτες.
Αυτό στον κώδικα το δείχνω με την απευθείας εναλλαγή των: char *cpx και char *cpy που στην ουσία είναι strings, αλλά δεν τα έχω ορίσει ως πίνακες. Τα έχω ορίσει απευθείας ως δείκτες (και αντί για malloc() / calloc() τα έχω αρχικοποίησει με τιμές κατευθείαν κατά τον ορισμό τους).
Παραθέτω και τον κώδικα...
- Κώδικας: Επιλογή όλων
/* --------------------------------------------------------------------------
* Παράδειγμα εναλλαγής δυο δεικτών (pointer swapping) ανεξαρτήτως τύπου.
* Τα ορίσματα της συνάρτησης swap_pointers() ορίζονται με τον γενικο τύπο: void,
* ώστε κατά την κλήση της συνάρτησης και με το αντίστοιχο type casting
* να λειτουργεί σωστά με οποιονδήποτε τύπο δεικτών.
*
* Το πρόγραμμα παρουσιάζει κώδικα για την εναλλαγή δεικτών σε 2 απλούς int,
* σε 2 συμβολοσειρές, σε 2 πίνακες από int και σε 2 struct.
* --------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_ARRELEMS 5 // απλά μια βοηθητική σταθερά
// -----------------------------------------------------------------------------------
// Η βασική μας συνάρτηση που εναλλάσσει δυο δείκτες, ανεξαρτήτως τύπου
//
void swap_pointers( void **x, void **y)
{
void *temp = *x;
*x = *y;
*y = temp;
return;
}
// -----------------------------------------------------------------------------------
// βοηθητική συνάρτηση που τυπώνει τα στοιχεία ενός πίνακα από int arr, μεγέθους len
//
void print_array( int arr[], int len )
{
register int i;
for (i=0; i < len; i++)
printf("%d ", arr[i]);
return;
}
// -----------------------------------------------------------------------------------
int main( void )
{
// swapping int pointers
int x=10, y=20;
int *px = &x, *py = &y;
puts("\nSWAPPING INTEGER POINTERS\n-------------------------");
printf("before:\t\tpx = %d,\tpy = %d\n", *px, *py);
swap_pointers( (void **) &px, (void **) &py );
printf("after :\t\tpx = %d,\tpy = %d\n\n", *px, *py);
// swapping char pointers
char *cpx = "string 1";
char *cpy = "string 2";
puts("\nSWAPPING CHARACTER POINTERS\n---------------------------");
printf("before:\t\tcpx = \"%s\",\tcpy = \"%s\"\n", cpx, cpy);
swap_pointers( (void **) &cpx, (void **) &cpy );
printf("after :\t\tcpx = \"%s\", \tcpy = \"%s\"\n\n", cpx, cpy);
// swapping array pointers
int xarr[MAX_ARRELEMS] = { 0, 1, 2, 3, 4 };
int yarr[MAX_ARRELEMS] = { 5, 6, 7, 8, 9 };
int *pxarr = xarr, *pyarr = yarr;
puts("\nSWAPPING ARRAY POINTERS\n-----------------------");
printf("before:\t\tpxarr = { ");
print_array( pxarr, MAX_ARRELEMS);
printf("}\tpyarr = { ");
print_array( pyarr, MAX_ARRELEMS);
puts("}");
swap_pointers( (void **) &pxarr, (void **) &pyarr );
printf("after :\t\tpxarr = { ");
print_array( pxarr, MAX_ARRELEMS);
printf("}\tpyarr = { ");
print_array( pyarr, MAX_ARRELEMS);
puts("}\n");
// swapping struct pointers
struct test { float w; float z; char s[256]; };
struct test xst = { .w = 10.0, .z = 20.0, .s = "x-string"};
struct test yst = { .w = 30.0, .z = 40.0, .s = "y-string" };
struct test *pxst = &xst, *pyst = &yst;
puts("\nSWAPPING STRUCT POINTERS\n------------------------");
printf( "before:\t\tpxst = {%.1f %.1f \"%s\"}\tpyst = {%.1f %.1f \"%s\"}\n",
pxst->w, pxst->z, pxst->s, pyst->w, pyst->z, pyst->s
);
swap_pointers( (void **) &pxst, (void **) &pyst );
printf( "before:\t\tpxst = {%.1f %.1f \"%s\"}\tpyst = {%.1f %.1f \"%s\"}\n",
pxst->w, pxst->z, pxst->s, pyst->w, pyst->z, pyst->s
);
fflush(stdin); getchar();
exit( EXIT_SUCCESS);
}