PDA

Επιστροφή στο Forum : δυναμικά struct C only



hayzel
11-01-11, 11:13
Έχω καιρό να χρησιμοποιήσω c, και έχω ξεχάσει διάφορα με έχει κάψει η ευκολία της C++/Qt :p.

Λοιπόν στο θέμα.
Χρησιμοποιώ ένα struct τύπου :


Struct List{
char** data;
count n;
};
Για μια δυναμική απλή λίστα strings.
Θέλω δυναμικά να αλλάξω το μέγεθος του data σε μια συνάρτηση:


struct* List myFunc(struct* List d)
{
free(d->data);
d->data=malloc(mysize+100);
return d;
};
To Παραπάνω δουλεύει όπως ακριβώς το περίμενα.
Η ερώτησή μου είναι αν υπάρχει τρόπος να γράψω την άνω συνάρτηση myFunc με return type void . Δηλαδή να περνώ την data by reference στην συνάρτηση:



void myFunc(struct* List d)
{
....
}
και η data να ενημερώνεται με τα απαραίτητα malloc μέσα στη συνάρτηση.

MichaelSE
11-01-11, 14:12
Επειδή κάνεις αλλαγές μόνο στη εσωτερική data (μήπως να αλλάξεις το όνομα της εσωτερικής για να συνεννούμαστε καλύτερα;), δεν χρειάζεται να επιστρέφεις την εξωτερική data. Ό,τι αλλαγές γίνουν στην εξωτερική data, θα επιστραφούν από την ίδια την παράμετρο. Άρα απλά δεν χρειάζεται το return και το return type (να είναι void)

........Auto merged post: MichaelSE πρόσθεσε 1 λεπτά και 19 δευτερόλεπτα αργότερα ........

Υ.Γ. Έχω κι εγώ χρόνια να χρησιμοποιήσω C, οπότε αυτά που λέω είναι με επιφύλαξη...

hayzel
11-01-11, 15:31
Βασικά ο κώδικας που έδωσα είναι ενδεικτικός αλλά όχι αυτός που έχω γράψει ο οποίος είναι αρκετά περίπλοκος.
Είμαι σχεδόν πεπεισμένος ότι αυτό που λες ότι αλλάζοντας κάτι στον πίνακα data μέσα στη συνάρτηση θα μείνει η αλλαγή και μετά την επιστροφή ΔΕΝ ισχύει, και αυτό είναι το πρόβλημα μου.
Εφόσον δουλέψω πάνω στα δεδομένα του πίνακα data* ισχύει αυτό που λες. Αν όμως δεσμέυσω νέο block μνήμης με την malloc και το ορίσω στον pointer data τότε κάτι διαφορετικό συμβαίνει και αυτό ακριβώς θέλω να κατανοήσω.

ΥΓ1. Δεν ξέρω αν πρόκειται για πρόβλημα του συγκεκριμένου compiler ή είναι χαρακτηριστικό της γλώσσας.
ΥΓ2. Δεν έχω πρόβλημα να επιστρέφω τον Pointer αφού δουλεύει κανονικά, θεωρητικό είναι το θέμα.

Παπι
11-01-11, 15:45
Εχεις δυο περιπτωσεις "επιστροφης" μεσου παραμετρου.

typedef struct taglist list;
struct taglist
{
char *arData;
int nData;
};

void myfunc(list* l)
{
l->arData =(char*) malloc(10);
l->nData = 10;
}

void myfunc1(list** l)
{
*l = (list*) malloc(sizeof(list));
}
int main()
{
list *l = NULL;
myfunc1(&l); //"επιστρεφεις" μια νεα list
myfunc(l);//"επιστρεφεις" νεους members στην υπαρκτη list
return 0;
}

virxen
11-01-11, 16:04
άλλο ένα παράδειγμα



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

struct List1{
char** data;
int n;
};

typedef struct List1* ListPtr ;
ListPtr myFunc1(ListPtr);

void myFunc2(ListPtr);

int main(){
ListPtr test;
test->data=(char **)malloc(10*sizeof(char *));
test->data[0]=(char *)malloc(10*sizeof(char));
strcpy(test->data[0],"yes!");
test->n=10;
printf("\ndata[0]=%s,n=%d",test->data[0],test->n);
printf("\n\nentering myfunc1....");
test=myFunc1(test);
printf("\ndata[0]=%s,n=%d",test->data[0],test->n);
printf("\n\nentering myfunc2....");
myFunc2(test);
printf("\ndata[0]=%s,n=%d",test->data[0],test->n);
getchar();
return 0;
}

ListPtr myFunc1(ListPtr d){
free(d->data);
d->data=(char **)malloc(100*sizeof(char *));
d->data[0]=(char *)malloc(10*sizeof(char));
strcpy(d->data[0],"no!");
d->n=5;
return d;
};
void myFunc2(ListPtr d){
free(d->data);
d->data=(char **)malloc(100*sizeof(char *));
d->data[0]=(char *)malloc(10*sizeof(char));
strcpy(d->data[0],"yes and no!");
d->n=13;
}

MichaelSE
11-01-11, 16:09
Βασικά ο κώδικας που έδωσα είναι ενδεικτικός αλλά όχι αυτός που έχω γράψει ο οποίος είναι αρκετά περίπλοκος.
Είμαι σχεδόν πεπεισμένος ότι αυτό που λες ότι αλλάζοντας κάτι στον πίνακα data μέσα στη συνάρτηση θα μείνει η αλλαγή και μετά την επιστροφή ΔΕΝ ισχύει, και αυτό είναι το πρόβλημα μου.
Εφόσον δουλέψω πάνω στα δεδομένα του πίνακα data* ισχύει αυτό που λες. Αν όμως δεσμέυσω νέο block μνήμης με την malloc και το ορίσω στον pointer data τότε κάτι διαφορετικό συμβαίνει και αυτό ακριβώς θέλω να κατανοήσω.

ΥΓ1. Δεν ξέρω αν πρόκειται για πρόβλημα του συγκεκριμένου compiler ή είναι χαρακτηριστικό της γλώσσας.
ΥΓ2. Δεν έχω πρόβλημα να επιστρέφω τον Pointer αφού δουλεύει κανονικά, θεωρητικό είναι το θέμα.

Αν δεσμεύσεις νέο block μνήμης με malloc στην ίδια εξωτερική μεταβλητή data, όντως χρειάζεται διπλός pointer. Όπως στη C++. Αν όμως δεσμεύσεις στην εσωτερική μεταβλητή data, δεν χρειάζεται διπλός pointer. Σκέψου ότι ο εξωτερικός pointer περνάει απλά σαν μία διεύθυνση. Δεν κάνεις αλλαγές σε αυτήν τη διεύθυνση, αλλά στα περιεχόμενά της (αλλάζοντας έναν εσωτερικό pointer).

Είναι ακριβώς η myfunc που έγραψε ο Παπι. Αν δεν δουλεύει κάτι περίεργο συμβαίνει. Ή κάτι που μου διαφεύγει επειδή ακριβώς μιλάμε για C και όχι για C++.

@ ADSLgr.com All rights reserved.