Je suis relativement nouveau en C et j'ai besoin d'aide pour les méthodes traitant des tableaux. Issu de la programmation Java, j'ai l'habitude de pouvoir dire int [] method()
pour renvoyer un tableau. Cependant, j'ai découvert qu'avec C, vous devez utiliser des pointeurs pour les tableaux lorsque vous les renvoyez. En tant que nouveau programmeur, je ne comprends vraiment pas du tout cela, même avec les nombreux forums que j'ai parcourus.
Fondamentalement, j'essaie d'écrire une méthode qui renvoie un tableau de caractères en C. Je vais fournir la méthode (appelons-la returnArray) avec un tableau. Il créera un nouveau tableau à partir du tableau précédent et y renverra un pointeur. J'ai juste besoin d'aide sur la façon de démarrer et de lire le pointeur une fois qu'il est envoyé hors du tableau. Toute aide expliquant cela est appréciée.
Format de code proposé pour la fonction de retour de tableau
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
Appelant de la fonction
int main(){
int i=0;
char array []={1,0,0,0,0,1,1};
char arrayCount=0;
char* returnedArray = returnArray(&arrayCount); ///is this correct?
for (i=0; i<10;i++)
printf(%d, ",", returnedArray[i]); //is this correctly formatted?
}
Je n'ai pas encore testé cela car mon compilateur C ne fonctionne pas pour le moment, mais j'aimerais comprendre cela
Réponses:
Vous ne pouvez pas retourner de tableaux à partir de fonctions en C.
returned
est créé avec une durée de stockage automatique et les références à celui-ci deviendront invalides une fois qu'il aura quitté sa portée de déclaration, c'est-à-dire lorsque la fonction sera renvoyée.Vous devrez allouer dynamiquement la mémoire à l'intérieur de la fonction ou remplir un tampon préalloué fourni par l'appelant.
Option 1:
allouer dynamiquement la mémoire à l'intérieur de la fonction (appelant responsable de la désallocation
ret
)Appelez ça comme ça:
Option 2:
remplir un tampon préalloué fourni par l'appelant (l'appelant alloue
buf
et passe à la fonction)Et appelez-le comme ça:
la source
Le traitement des tableaux par C est très différent de celui de Java et vous devrez ajuster votre réflexion en conséquence. Les tableaux en C ne sont pas des objets de première classe (c'est-à-dire qu'une expression de tableau ne conserve pas son "tableau" dans la plupart des contextes). En C, une expression de type "tableau à N éléments de
T
" sera implicitement convertie ("décroissance") en une expression de type "pointeur versT
", sauf lorsque l'expression de tableau est un opérande des opérateurs ou des opérateurssizeof
unaires&
, ou si le expression de tableau est une chaîne littérale utilisée pour initialiser un autre tableau dans une déclaration.Entre autres choses, cela signifie que vous ne pouvez pas passer une expression de tableau à une fonction et la recevoir en tant que type de tableau ; la fonction reçoit en fait un type de pointeur:
Dans l'appel à
foo
, l'expressionstr
est convertie du typechar [6]
àchar *
, c'est pourquoi le premier paramètre defoo
est déclaré à lachar *a
place dechar a[6]
. Danssizeof str
, puisque l'expression de tableau est un opérande de l'sizeof
opérateur, elle n'est pas convertie en type pointeur, vous obtenez donc le nombre d'octets dans le tableau (6).Si vous êtes vraiment intéressé, vous pouvez lire The Development of the C Language de Dennis Ritchie pour comprendre d'où vient ce traitement.
Le résultat est que les fonctions ne peuvent pas renvoyer de types de tableau, ce qui est bien puisque les expressions de tableau ne peuvent pas non plus être la cible d'une affectation.
La méthode la plus sûre consiste pour l'appelant à définir le tableau et à transmettre son adresse et sa taille à la fonction qui est censée y écrire:
Une autre méthode consiste pour la fonction à allouer le tableau dynamiquement et à renvoyer le pointeur et la taille:
Dans ce cas, l'appelant est responsable de la désallocation du tableau avec la
free
fonction de bibliothèque.Notez que
dst
dans le code ci-dessus se trouve un simple pointeur verschar
, pas un pointeur vers un tableau dechar
. La sémantique du pointeur et du tableau de C est telle que vous pouvez appliquer l'opérateur indice[]
à une expression de type tableau ou de type pointeur; les deuxsrc[i]
etdst[i]
accèdera aui
'ième élément du tableau (même s'ilsrc
n'a qu'un type de tableau).Vous pouvez déclarer un pointeur vers un tableau à N éléments
T
et faire quelque chose de similaire:Plusieurs inconvénients avec ce qui précède. Tout d'abord, les anciennes versions de C s'attendent
SOME_SIZE
à être une constante de compilation, ce qui signifie que cette fonction ne fonctionnera qu'avec une seule taille de tableau. Deuxièmement, vous devez déréférencer le pointeur avant d'appliquer l'indice, ce qui encombre le code. Les pointeurs vers des tableaux fonctionnent mieux lorsque vous avez affaire à des tableaux multidimensionnels.la source
bar
reçoit est un pointeur, pas un tableau. Dans le contexte d'une déclaration de paramètre de fonction,T a[N]
etT a[]
sont tous deux traités commeT *a
.void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
dernier paramètre doit être desize_t
type nonchar
.Je ne dis pas que c'est la meilleure solution ou une solution préférée au problème donné. Cependant, il peut être utile de se rappeler que les fonctions peuvent renvoyer des structures. Bien que les fonctions ne puissent pas retourner de tableaux, les tableaux peuvent être encapsulés dans des structures et la fonction peut renvoyer la structure transportant ainsi le tableau avec elle. Cela fonctionne pour les tableaux de longueur fixe.
J'invite à commenter les forces et les faiblesses de cette technique. Je n'ai pas pris la peine de le faire.
la source
CHAR_ARRAY returned
sur le tas? Il ne peut certainement pas le sur la pile (dans le cadre de la pile dereturnArray()
droite?Et cette mise en œuvre délicieusement diabolique?
array.h
principal c
la source
struct
tant que conteneur / objet de tableau. Pensez-y comme un std :: vector C ++. Le préprocesseur étendrait laint
version de ceci àstruct intArray { int* contents; int size; };
.Dans votre cas, vous créez un tableau sur la pile et une fois que vous quittez la portée de la fonction, le tableau sera désalloué. À la place, créez un tableau alloué dynamiquement et renvoyez un pointeur vers celui-ci.
la source
new
opérateur en C. C'est C ++.sizeof(char)
c'est garanti1
, donc dans ce cas, vous pouvez supprimer ce bitmalloc
.&arr
. Vous voulezarr
être unchar *
, et le transmettre en utilisantarr
.Vous pouvez le faire en utilisant la mémoire du tas (via l' invocation de malloc () ) comme les autres réponses rapportées ici, mais vous devez toujours gérer la mémoire (utilisez la fonction free () chaque fois que vous appelez votre fonction). Vous pouvez également le faire avec un tableau statique:
Vous pouvez ensuite l'utiliser sans vous soucier de la gestion de la mémoire.
Dans cet exemple, vous devez utiliser le mot-clé static dans la définition du tableau pour définir la durée de vie du tableau à long terme, afin qu'il ne soit pas détruit après l'instruction return. Bien sûr, de cette manière, vous occupez SIZE octets dans votre mémoire pendant toute la durée de vie de l'application, alors dimensionnons-la correctement!
la source
Votre méthode renverra une variable de pile locale qui échouera gravement. Pour renvoyer un tableau, créez-en un en dehors de la fonction, passez-le par adresse dans la fonction, puis modifiez-le, ou créez un tableau sur le tas et renvoyez cette variable. Les deux fonctionneront, mais le premier ne nécessite aucune allocation de mémoire dynamique pour le faire fonctionner correctement.
la source
Vous pouvez utiliser un code comme celui-ci:
Lorsque vous faites cela, la mémoire doit être libérée ultérieurement, en transmettant l'adresse à free.
Il existe d'autres options. Une routine peut renvoyer un pointeur vers un tableau (ou une partie d'un tableau) qui fait partie d'une structure existante. L'appelant peut passer un tableau et la routine écrit simplement dans le tableau, plutôt que d'allouer de l'espace pour un nouveau tableau.
la source