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

C: const pointer to const pointer


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

Δημοσ.

Ναι.

 

 

Με το προηγούμενο (const char * * const * const sarr) είχες έναν σταθερό δείκτη σε σταθερό δείκτη σε απλό δείκτη που έδειχνε σε σταθερές τιμές char.

 

Με αυτό (const char * const * const *sarr) έχεις έναν απλό δείκτη σε σταθερό δείκτη σε σταθερό δείκτη σε σταθερές τιμές char.

  • Απαντ. 32
  • Δημ.
  • Τελ. απάντηση

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

Δημοφιλείς Ημέρες

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

Δημοσ.

Ούτε αυτό :(

 

Μου χει σπάσει τα νεύρα !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 

 

 

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

#define pressENTER()								\
do{									\
	char mYcHAr;							\
	printf( "press ENTER..." );					\
	while ( (mYcHAr=getchar()) != '\n' && mYcHAr != EOF )		\
		;							\
}while(0)

/*********************************************************//**
*
*************************************************************
*/
int sarr_swap( char ***sarr1, char ***sarr2 )
{
char **temp = *sarr1;

if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 )
	return 0;	/* FALSE */

*sarr1 = *sarr2;
*sarr2 = temp;

return 1;		/* TRUE */
}


/*********************************************************//**
* @brief		Print to stdout the contents of a NULL terminated
*			array of c-strings.
* @param[in] sarr	The NULL terminated array of c-strings.
*************************************************************
*/
void sarr_print( char *const *const sarr )
{
int i = 0;

if ( !sarr )
	return;

for (i=0; sarr[i]; i++ )
	printf("%2d: %s\n", i, sarr[i] );

return;
}

/*********************************************************//**
* 
*************************************************************
*/
char **sarr_init( char ***sarr, const char *sinit )
{
int i = 0;

if ( !sarr || !*sarr || !sinit )
	return *sarr;

for (i=0; (*sarr)[i]; i++)
	strcpy( (*sarr)[i], sinit );

return *sarr;
}

/*********************************************************//**
* @brief		Free memory reserved for a NULL terminated array of c-strings.
* @param[in,out] sarr	Pointer to the NULL terminated array of c-strings.
* @remark		The array pointer is reset to NULL (that's why the array is
*			passed by reference).
*************************************************************
*/
void sarr_free( char ***sarr )
{
int i = 0;

if ( !sarr || !*sarr )
	return;

while ( (*sarr)[i] )
	free( (*sarr)[i++] );

*sarr = NULL;
}

/*********************************************************//**
* Reserve memory for a NULL terminated array of nstrings c-strings,
* each one being len characters long, excluding the nil terminating character.
*************************************************************
*/
char **sarr_new( const int nstrings, const int lenstr )
{
char **sarr = NULL;
int i=0;

if ( nstrings < 1 || lenstr < 1 )
	return NULL;

if ( NULL == (sarr = calloc( nstrings+1, sizeof(char *) )) )
	return NULL;

for (i=0; i < nstrings; i++)
{
	if ( NULL == (sarr[i] = calloc( lenstr+1, sizeof(char) )) )
	{
		int j;
		for (j=i-1; j > -1; j--)
			free( sarr[j] );
		free( sarr );
		return NULL;
	}
}

return sarr;
}

/* -------------------------------------------------------
*
* -------------------------------------------------------
*/
int main( void )
{
char **sarr1 = NULL, **sarr2 = NULL;

if ( NULL == (sarr1=sarr_new( 5, 80+1)) ) {
	puts("*** sarr1 = sarr_new() failed!");
	pressENTER();
	exit( EXIT_FAILURE );
}

if ( NULL == (sarr2=sarr_new( 5, 80+1)) ) {
	puts("*** sarr2 = sarr_new() failed!");
	sarr_free( &sarr1 );
	pressENTER();
	exit( EXIT_FAILURE );
}

sarr_init( &sarr1, "inited" );
sarr_print( sarr1 );

sarr_init( &sarr2, "INITED" );
sarr_print( sarr2 );

if ( !sarr_swap( &sarr1, &sarr2 ) )
	puts("*** sarr_swap() failed!");

sarr_print( sarr1 );
sarr_print( sarr2 );

sarr_free( &sarr1 );
sarr_free( &sarr2 );

pressENTER();
exit( EXIT_SUCCESS );
}

 

 

Θα μπορούσε κάποια ευγενική ψυχή να φτιάξει τις δηλώσεις των ορισμάτων της sarr_swap() και το temp, ώστε να κάνει αυτό που συζητάμε;

 

EDIT:

 

Έβαλα ένα if στην main() για όταν απoτυγχάνει η sarr_swap()

Δημοσ.

Όπως έχεις τον κώδικα, δεν θα δουλέψει.

 

Δες αυτό:

 

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

/*
* 
*/

typedef const char * const theString;
typedef const theString * const ptheString;
typedef const ptheString* sarr;

int main(int argc, char** argv) {

   //===================
   // Πρώτος πίνακας

   theString str1_1= "str1_1\0";
   theString str1_2= "str1_2\0";
   theString str2_1= "str2_1\0";
   theString str2_2= "str2_2\0";

   char** row1Tmp = (char**) malloc (sizeof(char*) * 2);
   row1Tmp[0] = &str1_1;
   row1Tmp[1] = &str1_2;

   ptheString row1 = row1Tmp;
   row1Tmp = NULL;

   char** row2Tmp = (char**) malloc (sizeof(char*) * 2);
   row2Tmp[0] = &str2_1;
   row2Tmp[1] = &str2_2;

   ptheString row2 = row2Tmp;
   row2Tmp = NULL;

   char*** sarr1Tmp = (char***) malloc( sizeof(char**) * 2);
   sarr1Tmp[0] = row1;
   sarr1Tmp[1] = row2;

   sarr sarr1 = sarr1Tmp;
   sarr1Tmp = NULL;

   //===========================
   // Δεύτερος πίνακας

   theString strNew1_1= "strNew1_1\0";
   theString strNew1_2= "strNew1_2\0";
   theString strNew2_1= "strNew2_1\0";
   theString strNew2_2= "strNew2_2\0";

   char** row21Tmp = (char**) malloc (sizeof(char*) * 2);
   row21Tmp[0] = &strNew1_1;
   row21Tmp[1] = &strNew1_2;

   ptheString row21 = row21Tmp;
   row21Tmp = NULL;

   char** row22Tmp = (char**) malloc (sizeof(char*) * 2);
   row22Tmp[0] = &strNew2_1;
   row22Tmp[1] = &strNew2_2;

   ptheString row22 = row22Tmp;
   row22Tmp = NULL;

   char*** sarr21Tmp = (char***) malloc( sizeof(char**) * 2);
   sarr21Tmp[0] = row21;
   sarr21Tmp[1] = row22;


   //Από εδώ και κάτω είναι το swap

   sarr sarr2 = sarr1Tmp;
   sarr1Tmp = NULL;

   sarr sarrTmp = sarr1;

   sarr1 = sarr2;

   sarr2 = sarr1;


   return (EXIT_SUCCESS);
}

 

 

(Πολύ γρήγορο παράδειγμα)

 

Παρατήρησε πως χτίζεται ο πίνακας που θες.

 

Εφόσον δηλώνεις σταθερούς δείκτες, δεν μπορείς να κάνεις malloc, γιατί ήδη ο δείκτης παίρνει τιμή. Σαν περιοχή μνήμης.

 

Και αυτή η περιοχή, έχει ήδη κάτι μέσα... ό,τι και να είναι αυτό. Και αυτό επίσης είναι σταθερό. Και δεν μπορεί να αλλάξει.

Δημοσ.

//Από εδώ και κάτω είναι το swap

 

sarr sarr2 = sarr1Tmp;

sarr1Tmp = NULL;

 

sarr sarrTmp = sarr1;

 

sarr1 = sarr2;

 

sarr2 = sarr1;//<-----------------------

 

 

μηπως θες να πεις

sarr2=sarrTmp;

Δημοσ.

Παιδιά έχω πάρει ήδη ένα Depon, πάω για 2ο... και άκρη δεν έχω βγάλει ακόμα :(

 

Χρειάζομαι ξεχωριστή ρουτίνα σαν την sarr_swap() που έχω ποστάρει, τα ορίσματα της οποίας να είναι πίνακες από c-strings (string arrays, sarr) δηλωμένα στην λίστα ορισμάτων της συνάρτησης έτσι ώστε μέσα στη συνάρτηση να μπορούν να αλλάζουν μονάχα οι δείκτες sarr1 και sarr2 και απολύτως τίποτε άλλο.

 

EDIT:

 

Δεν ξέρω αν σας βοηθάει, αλλά ουσιαστικά αυτό που χρειάζομαι είναι το αντίστοιχο του...

 

 

 

>
/* -------------------------------------------------------
*
* -------------------------------------------------------
*/
int s_swap( const char **s1, const char **s2 )
{
const char *temp = *s1;

if ( !s1 || !s2 )
	return 0;

*s1 = *s2;
*s2 = temp;
return 1;
}

int main( void )
{
char *s1 = "str1long";
char *s2 = "str2";

puts( s1 );
puts( s2 );
s_swap( (const char **)&s1, (const char **)&s2 );
puts( s1 );
puts( s2 );

return 0;
}

 

 

αλλά για πίνακες από strings αντί για σκέτα strings

 

Είναι απίστευτο το ότι έχω φάει τόσες ώρες χωρίς αποτέλεσμα :(

Δημοσ.

Α χα..

 

 

Τώρα κατάλαβα τι ζητάς...!

 

 

>
int swap( const char * const * const *input1, const char * const * const *input2)
{
 const char * const * const *tmp1 = input1;
 input1 = input2;
 input2 = tmp1;

 return 1;
}

 

Αυτό δεν σου τρέχει;

 

Ναι Virxen... αυτό ήθελα :P

Δημοσ.

...

Αυτό δεν σου τρέχει;

...

Δεν τρέχει το μπ&*%^%$λο !!! Δεν κάνει την εναλλαγή.

 

ΥΓ1. Φίλε Virxen, το πρόβλημα είναι όταν πάω να το κάνω ξεχωριστή συνάρτηση.

 

ΥΓ2. Με βλέπω να καταπίνω την εθνική μου (μας) περηφάνια και να ποστάρω στο StackOverflow :lol:

Δημοσ.

Α χα..

 

Δοκίμασέ το ως:

 

>
int swap_sarr(const char * const * const **in1, const char * const * const **in2)
{
 char*** tmp1;
 tmp1 = (*in1);
 (*in1) = (*in2);
 (*in2) = tmp1;
}

 

 

Και κάνε χρήση ως:

 

>
char*** test1, test2;

....

swap_sarr(&test1, &test2);

 

 

Λογικά αυτό θα δουλέψει.

Δημοσ.

Ήρθα σπίτι και νομίζω το κατάφερα!

 

>
int sarr_swap(const char *const **sarr1, const char *const **sarr2 )
{
const char *const *temp = NULL;

if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 )
	return 0;	/* FALSE */

temp = *sarr1;
*sarr1 = *sarr2;
*sarr2 = temp;

return 1;		/* TRUE */
}

Κατέφυγα όμως στο: http://cdecl.org για να δω ότι:

 

>
const char *const **sarr  // declare sarr as pointer to pointer to const pointer to const char
και
const char *const *temp   // declare temp as pointer to const pointer to const char

Το μόνο "πρόβλημα" που δεν ξέρω αν είναι κρίσιμης σημασίας είναι πως χωρίς casting στην κλήση...

 

>
sarr_swap( &sarr1, &sarr2 );

ο compiler παραπονιέται για πέρασμα ασύμβατων τύπων ως ορίσματα της συνάρτησης, αλλά ως προειδοποιήσεις και όχι ως fatal errors.

 

EDIT:

 

Λοιπόν νομίζω έκλεισε στο παραπάνω!

Και με 2 typedefs όλα πρέπει να είναι οκ...

 

>
typedef const char *const 	ConstString;
typedef const char *const * 	ArrayOfConstString;
...

int sarr_swap( ArrayOfConstString *sarr1, ArrayOfConstString *sarr2 )
{
ConstString *temp = NULL;

if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 )
	return 0;	/* FALSE */

temp = *sarr1;
*sarr1 = *sarr2;
*sarr2 = temp;

return 1;		/* TRUE */
}
...
int main( void )
{
...
if ( !sarr_swap( (ArrayOfConstString *)&sarr1, (ArrayOfConstString *)&sarr2 ) )
	puts("*** sarr_swap() failed!");
...
}

Δημοσ.

Από τη στιγμή που ήθελες να κάνεις απλώς swap πάντως θα μπορούσες να τα περάσεις σαν void** και να γλυτώσεις πολλούς πονοκεφάλους... :P

 

Πέρα από την πλάκα, δε νομίζω ότι κάνοντας τη συγκεκριμένη function πιο απαιτητική όσον αφορά τις παραμέτρους της προκύπτει ώφελος.

Δημοσ.

Από τη στιγμή που ήθελες να κάνεις απλώς swap πάντως θα μπορούσες να τα περάσεις σαν void** και να γλυτώσεις πολλούς πονοκεφάλους... :P

Όχι, το swap ήταν απλώς παράδειγμα. Εκεί που σκάλωσα άσχημα και ταλαιπωρήθηκα και ταλαιπώρησα και τα παιδιά ήταν στο ότι οι δείκτες sarr δεν μπορούν να γίνουν const χωρίς να μεσολαβήσει κι άλλος δείκτης :(

 

Η τελευταία δημοσίευση του timonkaipumpa δείχνει αυτό ακριβώς (btw, timon είσαι μεγάλη μορφή! :) )

 

Πέρα από την πλάκα, δε νομίζω ότι κάνοντας τη συγκεκριμένη function πιο απαιτητική όσον αφορά τις παραμέτρους της προκύπτει ώφελος.

Χρειάζομαι εγγύηση πως κάποιες συναρτήσεις δεν θα πειράξουν καθόλου τον πίνακα.

Δημοσ.

Χρειάζομαι εγγύηση πως κάποιες συναρτήσεις δεν θα πειράξουν καθόλου τον πίνακα.

 

...άρα χρειάζεσαι μια γλώσσα που δεν επιτρέπει casts. ;-)

Δημοσ.

Γιατί ρε παιδιά;

 

Έτσι όπως το κάναμε τώρα δεν είναι εγγυημένο πως π.χ. η swap μέσα της δεν μπορεί ούτε και κατά λάθος να αλλάξει τα περιεχόμενα του πίνακα (π.χ. να βάλει τον δείκτη sarr[5] να δείχνει κάπου αλλού, ή να αλλάξει τα περιεχόμενα του string *(sarr[3]) );

 

EDIT:

 

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

 

>
int sarr_swap(ArrayOfConstString *sarr1, ArrayOfConstString *sarr2 )
{
ConstString *temp = NULL;

if ( !sarr1 || !*sarr1 || !sarr2 || !*sarr2 )
	return 0;	/* FALSE */

temp = *sarr1;
*sarr1 = *sarr2;
*sarr2 = temp;

**sarr2[0] = 'N';	/* <--- IMPOSSIBLE */
*sarr2[0] = *sarr2[1];	/* <--- IMPOSSIBLE */

return 1;		/* TRUE */
}

δηλαδή βαράει errors ο compiler στις 2 προτελευταίες γραμμές, as it should...

 

>
temp1.c:50:2: error: assignment of read-only location '***sarr2'
temp1.c:51:2: error: assignment of read-only location '**sarr2'

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

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