web-dev-qa-db-fra.com

C Attribuer un pointeur à NULL

Je me méprends sur quelque chose de basique à propos des pointeurs en C, cela devrait être simple mais la recherche n'apporte rien. Je ne comprends pas le comportement du code suivant;

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

void my_function(char *);

int main(int argc, char *argv[]) {
    char *ptr;
    ptr = malloc(10);

    if(ptr != NULL) printf("FIRST TEST: ptr is not null\n");
    else printf("FIRST TEST: ptr is null\n");

    my_function(ptr);

    if(ptr != NULL) printf("SECOND TEST: ptr is not null\n");
    else printf("SECOND TEST: ptr is null\n");
}

void my_function(char *a) {
    a = NULL;
}

Quelles sorties;

FIRST TEST: ptr is not null
SECOND TEST: ptr is not null

Pourquoi le deuxième test voit-il toujours le pointeur comme non NULL? J'essaie d'utiliser une affectation de pointeur NULL comme une sorte de "drapeau de retour" pour indiquer une certaine défaillance de la fonction. Mais après avoir testé le pointeur par la suite, il ne semble pas être NULL.

12
lynks

C'est parce que le pointeur est passé par valeur et non par référence. Si vous souhaitez modifier le pointeur à l'intérieur de la fonction, vous devez passer le pointeur réel en tant que pointeur, c'est-à-dire un pointeur sur un pointeur:

void my_function(char **a)
{
    *a = NULL;
}

Utilisez l'opérateur d'adresse _ & lorsque vous appelez la fonction pour obtenir l'adresse du pointeur:

my_function(&ptr);
32

Votre instruction a=NULL Dans my_function() définit en effet la valeur de a sur NULL, mais a est une variable locale de cette fonction. Lorsque vous avez passé ptr à my_function() dans main(), la valeur de ptr a été copiée dans a. Je suppose que toute votre confusion provient du * utilisé avant a dans la définition de my_function().

Les pointeurs sont généralement passés aux fonctions lorsque nous voulons manipuler les valeurs d'origine vers lesquelles ces pointeurs pointent, à partir de la fonction appelée, et cela se fait par dereferencing ces pointeurs à partir des fonctions appelées. Dans ce cas, si vous aviez utilisé ce:

*a= blah blah;

il se serait reflété dans la valeur à l'adresse pointée par ptr dans main(). Mais comme vous voulez changer la valeur de ptr elle-même, vous devez pouvoir d'avoir un moyen de manipulate depuis my_function(). Pour cela, vous utilisez un pointer-to-pointer, c'est-à-dire de type char**. Vous passez un tel char** Comme argument pour my_function(() et l'utiliser pour modifier la valeur de ptr. Voici la variation de votre code qui le ferait pour vous:

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

void my_function(char **); // Change char* to char**

int main(int argc, char *argv[]) {
    char *ptr;
    ptr = malloc(10);

    if(ptr != NULL) printf("FIRST TEST: ptr is not null\n");
    else printf("FIRST TEST: ptr is null\n");

    my_function(&ptr); //You pass a char**

    if(ptr != NULL) printf("SECOND TEST: ptr is not null\n");
    else printf("SECOND TEST: ptr is null\n");
}

void my_function(char **a) {  //Change char* to char** here
    *a = NULL;
}
6
Rüppell's Vulture

en C, un appel de fonction comme foo(a) ne changera jamais la valeur de a.

2
richselian

Votre fonction doit prendre un char** a si vous voulez modifier ce qu'il pointe. Cela est dû au fait que les pointeurs sont copiés comme arguments d'une fonction, ce qui signifie que toutes les modifications que vous lui apportez à l'intérieur ne seront pas vues en dehors de la fonction, car cela modifie une copie.

Si vous souhaitez le modifier et le voir en dehors de la portée de la fonction, vous devez ajouter une autre indirection.

1
Tony The Lion

lors du passage du pointeur à la fonction, le pointeur est copié dans l'étendue des fonctions. vous devez utiliser un pointeur de pointeur si vous voulez faire de telles choses. Un pointeur n'est fondamentalement qu'un entier/long

0
vszurma

Votre problème est que mon_pointer n'écrit pas sur le pointeur "ptr", mais sur sa copie, "* a".

Vous devez transmettre l'adresse de "ptr" à ce que vous voulez.

0
user2054656