Lorsque j'ai découvert les pointeurs, on m'a dit qu'ils étaient utiles car ils nous permettaient de modifier certaines variables introduites dans des fonctions qui ne seraient normalement pas modifiables. Par exemple:
void first_to_n(int a[], int n){
a[0] = n;
}
Donc à la fin de ceci, "b" est égal à "a", et "a" est égal à 0, même si "a" et "b" ne le feraient pas ne peut normalement pas être modifiable.
Quand je parle de listes et, plus précisément, d'ajouter un élément à une liste, je peux utiliser une fonction comme celle-ci:
struct list{
int n;
struct list *next;
}
struct list *first = NULL;
int main(){
int n = 3;
first = add_to_list(first, n);
}
struct list *add_to_list(struct list *first, int n){
struct list *new_node;
new_node = malloc(sizeof(struct list));
if(new_node == NULL) exit(EXIT_FAILURE);
new_node->value = n;
new_node->next = first;
return new_node;
}
Ce qui me préoccupe spécifiquement, c'est pourquoi la fonction ne peut pas simplement renvoyer un type void, et au lieu d'écrire "return new_node" , je ne peux pas simplement écrire "first = new_node" em>. Parce que le premier est un pointeur, si je le modifie n'importe où dans mon programme, le pointeur d'origine doit également être modifié, tout comme cela s'est produit dans le premier exemple que j'ai fait, n'est-ce pas?
Aussi, un peu de question sans rapport, mais si j'ai une fonction comme celle-ci:
void copy(int *p, int *s);
int main(){
int a = 4, b = 10, *p = &a, *s = &b;
copy(p, s);
}
void copy(int *p, int *s){
*s = *p;
*p = 0;
}
Le premier élément du vecteur original a, qui disons est déclaré dans main, est également modifié, non? Parce que les vecteurs peuvent être considérés comme des pointeurs
4 Réponses :
Lorsque j'ai découvert les pointeurs, on m'a dit qu'ils étaient utiles car ils nous permettaient de modifier certaines variables introduites dans des fonctions qui ne seraient normalement pas modifiables.
Entre autres, comme la création de structures de données non triviales et pour éviter les copies.
Parce que le premier est un pointeur, si je le modifie n'importe où dans mon programme, le pointeur d'origine doit également être modifié, comme cela s'est produit dans le premier exemple que j'ai fait, n'est-ce pas?
first(le paramètre) est une copie defirst(le global). Par conséquent,first = new_nodene modifierait que votre pointeur, pas le pointeur global.Ceci est plus clair dans votre premier exemple:
void copy(int *p, int *s){ *s = *p; *p = 0; }
Disons que nous avons quelque chose comme le code suivant
void func(int *x, int **y)
{
*y = x;
}
int main(void)
{
int a = 10;
int b = 20;
int *c = &a; // Make c point to the variable a
func(&b, &c);
}
Ce qui se passe lorsque funcA est appelé, c'est que la valeur de un est copié dans la variable distincte x à l'intérieur de la fonction. Lors de l'appel, deux copies de la valeur 10 sont stockées à différents endroits. Lorsque l'affectation x = 0 est effectuée à l'intérieur de la fonction, seule la variable locale x est modifiée.
Pour funcB c'est exactement la même chose. La valeur de la variable b est copiée dans la variable séparée y de la fonction. Cela signifie qu'il existe deux variables séparées et distinctes pointant vers le même emplacement. Mais une fois que l'affectation y = NULL est terminée, ce n'est plus vrai. La variable y ne pointe plus vers le même emplacement, mais dans la fonction main b n'est pas modifiée car seule une copie de la valeur a été transmise à la fonction.
Si nous prenons maintenant un exemple légèrement différent
void funcA(int x)
{
x = 0;
}
void funcB(int *y)
{
y = NULL;
}
int main(void)
{
int a = 10;
int *b = &a;
funcA(a);
funcB(b);
}
Une fois la fonction appelée, alors c code> ne pointe plus vers a , il pointe vers b . C'est parce que pour le deuxième argument, la valeur que nous passons est & c qui est un pointeur vers la variable c . À l'intérieur de la fonction, nous pouvons ensuite utiliser l'opérateur de déréférencement pour accéder à ce vers quoi y pointe (qui sera la variable c dans la fonction main ) .
Pourquoi passez-vous «b» par valeur si func prend un pointeur comme premier argument?
@ machine_1 Oups!
Ce qui me préoccupe spécifiquement, c'est pourquoi la fonction ne peut pas simplement retourner un type void, et au lieu d'écrire "return new_node", je ne peux pas simplement écrivez "first = new_node".
Comme les autres réponses l'expliquent, vous ne pouvez pas car first est une "copie" du pointeur en dehors de la fonction. Si toutefois vous deviez plutôt changer la fonction de telle sorte que vous passiez un 'pointeur vers le pointeur' plutôt que juste le 'pointeur', alors vous pourriez changer la valeur externe, qui est ce qui se passe dans la fonction 'copier'. < / p>
Ceci utilise un pointeur vers une chaîne littérale.
Le pointeur est passé à modifypointer () où il est modifié pour pointer vers une autre chaîne littérale. La nouvelle chaîne littérale est imprimée dans la fonction, mais main () imprime toujours l'original.
Le pointeur est passé en tant que pointeur vers lui-même dans modifypointertopointer () où il est déréférencé pour pointer vers une autre chaîne littérale. Maintenant, la fonction imprime la nouvelle chaîne littérale et main () imprime également la nouvelle chaîne littérale.
Dans votre dernier exemple, first = new_node; pourrait être utilisé sauf que la fonction déclare une variable shadow first et que le first global n'est plus dans le portée de la fonction.
#include <stdio.h>
void modifypointer( char *mod) {
mod = "modify pointer";
printf ( "%s\n", mod);
}
void modifypointertopointer( char **ptrmod) {
*ptrmod = "modify pointer to pointer";
printf ( "%s\n", *ptrmod);
}
int main( void) {
char *text = "original";
printf ( "%s\n", text);
modifypointer ( text);
printf ( "%s\n", text);
modifypointertopointer ( &text);
printf ( "%s\n", text);
return 0;
}
La chose importante que vous devez apprendre ici est que les arguments en C sont passés par valeur, c'est-à-dire que la valeur est copiée. Cela vaut bien sûr aussi pour les pointeurs, si vous passez une variable qui est un pointeur vers quelque chose, alors ce qui est copié est le pointeur. Pour émuler le passage par référence, vous devez passer un pointeur vers la variable qui, pour les variables de pointeur, devient des pointeurs vers des pointeurs.
@Someprogrammerdude Disons donc que je passe un pointeur vers une fonction en tant que variable. À l'intérieur de la fonction, le pointeur est réaffecté pour pointer vers une autre variable. Le pointeur d'origine serait-il également modifié ou pointerait-il toujours vers l'ancienne variable?
En remarque, ne déclarez pas plus d'une variable sur une seule ligne. Utilisez une ligne par déclaration. C'est plus clair de cette façon.
@FoxyIT
le pointeur est réaffecté- la copie du pointeur est réaffectée. Ainsi, le pointeur d'origine continuera à pointer vers la même mémoire, car la valeur du pointeur d'origine ne changera pas. Mais si vous modifiez la mémoire vers laquelle pointe le pointeur, elle peut être modifiée par n'importe quel pointeur qui pointe vers le même endroit.@FoxyIT: les paramètres sont toujours passés par valeur aux fonctions en C. Si la variable est un pointeur, alors la variable contient simplement l'adresse d'un certain objet en mémoire. Ainsi, la valeur de l'adresse est à nouveau passée par le paramètre. Pour tout paramètre de fonction
x, écrirex = quelque chose;à l'intérieur de la fonction n'aura aucun effet sur la variable d'origine en dehors de la fonction.