Tableau sont passés par valeur ou par référence?
Je sais pour sûr que
function(int *a); function(int a[]);
dans C sont les mêmes, la fonction(int a[]) sera traduit en fonction(int *a)
int *a = malloc(20);
int b[] = {1,2,3,4,5};
Ces deux ne sont pas les mêmes, le premier est un pointeur, le deuxième est un tableau. Qu'advient-il lorsque j'appelle la fonction(b)?(fonction(int *))
Je sais que b est sur la pile, alors comment est-il passé à cette fonction?
Deuxièmement, les chaînes:
char *c1 = "string";
char c2 [] = "string";
Dans ce cas, je ne sais pas où est c1, et je suppose que c2 est sur la pile.
Supposons que la fonction est maintenant: fonction(char *c), qui est la même que la fonction(char c[]), qu'advient-il lorsque j'appelle la fonction(c1), et la fonction(c2), les cordes vont être passés par référence ou de valeur?
Oui, j'ai fait tout ce que vous avez mentionné, mais maintenant je suis en train de voir C, jusqu'à l'assemblage des verres.
Ensuite, compilez avec
Ensuite, compilez avec
gcc -Wall -fverbose-asm -S yourfile.c
puis regardez dans yourfile.s
OriginalL'auteur AR89 | 2012-11-19
Vous devez vous connecter pour publier un commentaire.
Il y a un point crucial à faire ici, tout est vraiment passé en valeur par exemple, cela va passer une copie de
a
àfoo()
(qui se trouve être un pointeur vers la mémoire):C'est pourquoi, si vous faites quelque chose comme cela dans
foo()
il n'a pas vraiment changer le pointeur de laa
dansmain()
mais les changements de la copie locale:En d'autres termes, vous pouvez utiliser
foo()
'copie locale dea
pour changer la mémoire souligné par 'a', mais pas de changement de cea
points de dansmain()
.Maintenant, de passer à quelque chose de "par référence" vous passez une copie d'un pointeur de pointeur à la fonction (quelque chose comme un->b->mémoire):
Ainsi, lorsque vous affectez dans
foo()
de change le pointeur dansmain()
:Maintenant de répondre à certaines de vos questions, lorsque vous utilisez un nom de la matrice de il est converti en un pointeur vers le premier élément du tableau:
Les deux derniers appels de fonction sont équivalents en ce qu'ils ont tous les deux de passer un pointeur vers le premier élément de la mémoire, la différence est que la mémoire
a
est alloué sur le tas, la mémoire deb
cependant, est alloué sur la pile.Enfin, les chaînes, les éléments suivants sont similaires, en ce que le même principe s'applique, mais le premier est un constante chaîne de caractères littérale et devrait être défini comme
const
et vous devriez pas de tenter de le modifier n'importe où, mais vous pouvez changer la seconde:func (int x)
est par valeur etfunc (int* x)
est par référence. Parce que si c'est en val ou par ref dépend vraiment de la intention de la fonction. Sinon, on peut juste dire que votre exemplefoo(int **a)
ne passe pas à quoi que ce soit par référence, il est simplement en passant un pointeur de pointeur de valeur.Je pense, à mon humble avis, que le fait de dire que quelque chose est passé par référence est la raison pour laquelle tous les débutants d'essayer d'attribuer à un pointeur à l'intérieur d'une fonction et de s'attendre à ce que ça change quelque part d'autre.
Un débutant avec pas programmeur d'expérience est probablement moins susceptibles de le faire, que permet de dire un programmeur Java apprentissage C. de toute façon, tous les débutants aussi essayer de retourner un pointeur vers une variable locale d'une fonction. J'ai l'impression que floue des termes comme "par référence", voire de "pointeur", n'est pas vraiment utile pour un débutant, il est probablement mieux d'expliquer ce qui se passe dans le binaire, sous le capot.
OriginalL'auteur iabdalkader
De K&R2
La déclaration d'argument
char c2 []
est juste sucre syntaxique pourchar* c2
.Tout C est adoptée comme valeur. Pour de plus amples explications de cet usage de cette lien.
Aussi Eli Bendersky a une excellente l'article discuter de la même chose.
OriginalL'auteur Shash
Lorsque vous passer un tableau à une fonction attend un pointeur, la référence du tableau "désintègre" en un pointeur sur son premier élément.
http://c-faq.com/aryptr/aryptrequiv.html
Le réel en passant à la fonction est par référence, ce qui est fait par le compilateur en plaçant l'adresse (pointeur) sur la pile ou dans un PROCESSEUR inscrire.
Chaînes ne font pas exception, car ils sont simplement des tableaux de caractères.
En effet, mais je tente une sorte de pédagogie de la simplification. Pour juste répondre "tout ce qui est passé par valeur" ne va pas rendre la vie plus facile pour tout programmeur débutant.
Merci pour la réponse, mais je cherchais une explication plus détaillée, je suis un débutant avec C, mais j'ai déjà eu l'expérience avec de l'assemblée et de Java, j'ai essayé de voir la correspondance entre C appels de fonction et les procédures de l'assemblée.
Alors peut-être que vous devriez avoir fait que ce soit clair dans la question...
Je ne m'attendais pas à recevoir une simplification pédagogique, je vais y réfléchir à l'avenir des questions btw.
OriginalL'auteur Lundin
char c2[] = "string"
il ne sera pas en lecture seule mémoire.chaîne sera sur
readonly
une copie de celui-ci est copié dansc2
tableau sur la pile.C'est une façon possible de la mettre en œuvre, mais vous parlez de détails de mise en œuvre. Le résultat final est quelque chose qui n'est pas en lecture seule mémoire.
Techniquement, la traduction littérale de "chaîne" sera toujours placé dans la mémoire en lecture seule, mais le compilateur est libre pour optimiser son allocation de là, et seulement allouer de l'espace pour c2. C'est, si le compilateur est écrit pour un pur en fonction de RAM système, tel qu'un PC. Sinon, rien ne peut être fait et le littéral de chaîne doit être alloué dans la mémoire ROM.
Techniquement, il n'est pas nécessaire que la mémoire en lecture seule existe pas du tout (je ne peux penser à un couple C implémentations qui ne l'ont pas), la seule chose dont nous pouvons être sûrs, c'est que
c2
n'est pas en lecture seule mémoire.OriginalL'auteur Omkant
Si votre pense que c'est Appel par Valeur puis essayez d'exécuter ceci:
Dans les deux bubbleSort() et displayArray() après bubblesort (), affichera les mêmes résultats.
Si vous appelez la fonction(a) lorsque a est une matrice, il va passer l'Adresse de Base d'une. Ainsi, son fond de Appel par Ref.
Aussi,
sont exactement les MÊMES !
Dans les deux cas, c pointe vers le premier élément de la chaîne. Aussi, la 1ère chaîne n'est PAS, et je veux dire PAS constante. Essayez de la modifier. Il le fera.
OriginalL'auteur Nikhil Prasad
Les tableaux sont passés par référence, pourquoi ? parce que vous avez passé l'adresse de pointeur en valeur de sorte qu'un changement sur le pointeur va changer sur le fait de la mémoire ne sont pas l'adresse de pointeur lui-même, la modification du pointeur ne va pas remplacer l'original pointeur de la fonction, de sorte que lorsque vous tapez un = ANOTHER_POINTER à l'intérieur de cette fonction, il ne sera pas la perte du tableau transmis après l'utilisation de la fonction
int a[] est équivalent à int un et lors de l'appel de la fonction foo(int a) il obtenir l'adresse de pointeur
maintenant, si vous voulez changer le pointeur auto, vous pouvez passer le pointeur d'adresse par référence foo(int *& a) donc en train de changer sur le pointeur d'adresse a = ANOTHER_POINTER va changer l'adresse du pointeur
Non, vous ne pouvez pas passer le pointeur d'adresse par le biais de la référence C++ mécanisme dans le langage C.
foo(int *& a)
ne compilera pas.merci pour l'information
OriginalL'auteur Omar Freewan
Les tableaux sont toujours passés par référence (pointeur).
Si vous voulez les transmettre à l'aide de la valeur, de l'encapsuler dans un
struct
. Qui seraient le résultat d'exploitation sur une copie du tableau original. Exemple montré ci-dessous:Le premier argument de foo est struct objet, qui détient une copie du tableau. Deuxième argument est la matrice de référence.
OriginalL'auteur anishsane