Pourquoi utiliser double pointeur? ou Pourquoi utiliser des pointeurs sur des pointeurs?

quand utiliser un double pointeur en Do? Quelqu'un peut-il expliquer avec un exemple?

Ce que je sais, c'est qu'un double pointeur est un pointeur vers un pointeur. Pourquoi aurais-je besoin d'un pointeur vers un pointeur?

186
demandé sur BЈовић 2011-04-07 16:08:56

19 réponses

Si vous voulez avoir une liste de caractères (un mot), vous pouvez utiliser char *word

Si vous voulez une liste de mots (une phrase), vous pouvez utiliser char **sentence

Si vous voulez une liste de phrases (un monologue), vous pouvez utiliser char ***monologue

Si vous voulez une liste de monologues (une biographie), vous pouvez utiliser char ****biography

Si vous voulez une liste de biographies (une bio-bibliothèque), vous pouvez utiliser char *****biolibrary

Si vous voulez une liste de bio-bibliothèques (une ??lol) , vous pouvez utiliser char ******lol

... ...

oui, je sais que ces peut-être pas le meilleur des structures de données

375
répondu pmg 2011-04-07 12:23:37

une raison est que vous voulez changer la valeur du pointeur passé à une fonction comme argument de fonction, pour ce faire, vous avez besoin d'un pointeur vers un pointeur.

en termes simples, utilisez ** lorsque vous voulez préserver (ou conserver le changement) L'Allocation de mémoire ou L'affectation même en dehors d'un appel de fonction. (donc, passer une telle fonction avec arg double pointeur.)

C'est peut-être pas un très bon exemple, mais vous l'usage de base:

void allocate(int** p)
{
  *p = (int*)malloc(sizeof(int));
}

int main()
{
  int* p = NULL;
  allocate(&p);
  *p = 42;
  free(p);
}
146
répondu Asha 2013-06-28 20:29:48

Voici une réponse SIMPLE!!!!

  • permet de dire que vous avez un pointeur que sa valeur est une adresse.
  • mais maintenant, vous voulez changer cette adresse.
  • , vous pouvez, en faisant pointer1 = pointer2, et pointer1 aurait maintenant l'adresse de pointer2.
  • mais! si vous voulez qu'une fonction fasse cela pour vous, et vous voulez que le résultat persiste après que la fonction soit faite, vous devez faire quelque travail supplémentaire, vous avez besoin d'un nouveau pointer3 juste pour pointer vers le pointer1, et passer le pointer3 à la fonction.

  • voici un exemple amusant (jetez un oeil à la sortie ci-dessous d'abord, pour comprendre!):

#include <stdio.h>

int main()
{

    int c = 1;
    int d = 2;
    int e = 3;
    int * a = &c;
    int * b = &d;
    int * f = &e;
    int ** pp = &a;  // pointer to pointer 'a'

    printf("\n a's value: %x \n", a);
    printf("\n b's value: %x \n", b);
    printf("\n f's value: %x \n", f);
    printf("\n can we change a?, lets see \n");
    printf("\n a = b \n");
    a = b;
    printf("\n a's value is now: %x, same as 'b'... it seems we can, but can we do it in a function? lets see... \n", a);
    printf("\n cant_change(a, f); \n");
    cant_change(a, f);
    printf("\n a's value is now: %x, Doh! same as 'b'...  that function tricked us. \n", a);

    printf("\n NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a' \n");
     printf("\n change(pp, f); \n");
    change(pp, f);
    printf("\n a's value is now: %x, YEAH! same as 'f'...  that function ROCKS!!!. \n", a);
    return 0;
}

void cant_change(int * x, int * z){
    x = z;
    printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", x);
}

void change(int ** x, int * z){
    *x = z;
    printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", *x);
}
  • et voici le résultat:
 a's value: bf94c204

 b's value: bf94c208 

 f's value: bf94c20c 

 can we change a?, lets see 

 a = b 

 a's value is now: bf94c208, same as 'b'... it seems we can, but can we do it in a function? lets see... 

 cant_change(a, f); 

 ----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see

 a's value is now: bf94c208, Doh! same as 'b'...  that function tricked us. 

 NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a' 

 change(pp, f); 

 ----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see

 a's value is now: bf94c20c, YEAH! same as 'f'...  that function ROCKS!!!. 
59
répondu Brian Joseph Spinos 2016-02-24 20:15:53

ajout à la réponse Asha , si vous utilisez un seul pointeur vers l'exemple ci-dessous (par exemple alloc1 ()), vous perdrez la référence à la mémoire allouée à l'intérieur de la fonction.

void alloc2(int** p) {
   *p = (int*)malloc(sizeof(int));
   **p = 10;
}

void alloc1(int* p) {
   p = (int*)malloc(sizeof(int));
   *p = 10;
}

int main(){
   int *p;
   alloc1(p);
   //printf("%d ",*p);//value is undefined
   alloc2(&p);
   printf("%d ",*p);//will print 10
   free(p);
   return 0;
}

la raison pour laquelle il se produit comme ceci est que dans alloc1 le pointeur est passé en valeur. Ainsi, lorsqu'il est réassigné au résultat de l'appel malloc à l'intérieur de alloc1 , le changement ne se rapporte pas au code dans une portée différente.

34
répondu Silviu 2017-05-23 12:34:51

1. Concept De Base -

lorsque vous déclarez ce qui suit: -

1. char *ch - (appelé pointeur de caractère)

- ch contient l'adresse d'un caractère unique.

- (*ch) déréférencera à la valeur du caractère..

2. char * * ch -

'ch' contient la adresse d'un Tableau de pointeurs de caractère. (1)

'*ch " contient l'adresse d'un caractère unique. (Notez qu'il est différent de 1, en raison de la différence dans la déclaration).

(**ch) déréférencera à la valeur exacte du caractère..

ajouter plus de pointeurs élargissent la dimension d'un type de données, du caractère à la chaîne, au tableau de chaînes, et ainsi de suite... Vous pouvez le relier à une matrice 1D, 2d, 3d..

ainsi, l'usage du pointeur dépend de la façon dont vous le déclarez.

voici un code simple..

int main()
{
    char **p;
    p = (char **)malloc(100);
    p[0] = (char *)"Apple";      // or write *p, points to location of 'A'
    p[1] = (char *)"Banana";     // or write *(p+1), points to location of 'B'

    cout << *p << endl;          //Prints the first pointer location until it finds '"151900920"'
    cout << **p << endl;         //Prints the exact character which is being pointed
    *p++;                        //Increments for the next string
    cout << *p;
}

2. Une autre Application de pointeurs doubles -

(cela couvre également les passer par référence)

supposons que vous voulez mettre à jour un caractère d'une fonction. Si vous essayez ce qui suit : -

void func(char ch)
{
    ch = 'B';
}

int main()
{
    char ptr;
    ptr = 'A';
    printf("%c", ptr);

    func(ptr);
    printf("%c\n", ptr);
}

la sortie sera AA. Cela ne fonctionne pas, car vous avez "passé la valeur" à la fonction.

la bonne façon de le faire serait -

void func( char *ptr)        //Passed by Reference
{
    *ptr = 'B';
}

int main()
{
    char *ptr;
    ptr = (char *)malloc(sizeof(char) * 1);
    *ptr = 'A';
    printf("%c\n", *ptr);

    func(ptr);
    printf("%c\n", *ptr);
}

étend maintenant cette exigence pour mettre à jour une chaîne au lieu du caractère.

Pour cela, vous devez recevoir le paramètre dans la fonction comme un double pointeur.

void func(char **str)
{
    strcpy(str, "Second");
}

int main()
{
    char **str;
    // printf("%d\n", sizeof(char));
    *str = (char **)malloc(sizeof(char) * 10);          //Can hold 10 character pointers
    int i = 0;
    for(i=0;i<10;i++)
    {
        str = (char *)malloc(sizeof(char) * 1);         //Each pointer can point to a memory of 1 character.
    }

    strcpy(str, "First");
    printf("%s\n", str);
    func(str);
    printf("%s\n", str);
}

Dans cet exemple, la méthode attend un double pointeur en paramètre à mettre à jour la valeur d'une chaîne.

19
répondu Bhavuk Mathur 2018-05-17 13:21:44

j'ai vu un très bon exemple aujourd'hui, de ce billet de blog , comme je résume ci-dessous.

Imaginez que vous avez une structure pour les noeuds dans une liste liée, qui est probablement

typedef struct node
{
    struct node * next;
    ....
} node;

Maintenant vous voulez implémenter une fonction remove_if , qui accepte un critère de suppression rm comme l'un des arguments et traverse la liste liée: si une entrée satisfait le critère( quelque chose comme rm(entry)==true ), son noeud sera supprimé de la liste. À la fin, remove_if renvoie la tête (qui peut être différente de la tête originale) de la liste liée.

vous pouvez écrire

for (node * prev = NULL, * curr = head; curr != NULL; )
{
    node * const next = curr->next;
    if (rm(curr))
    {
        if (prev)  // the node to be removed is not the head
            prev->next = next;
        else       // remove the head
            head = next;
        free(curr);
    }
    else
        prev = curr;
    curr = next;
}

comme votre boucle for . Le message est, sans pointeurs doubles , vous devez maintenir une prev variable pour réorganiser les pointeurs , et gérer les deux cas différents.

mais avec des pointes doubles, vous peut réellement écrire

// now head is a double pointer
for (node** curr = head; *curr; )
{
    node * entry = *curr;
    if (rm(entry))
    {
        *curr = entry->next;
        free(entry);
    }
    else
        curr = &entry->next;
}

vous n'avez pas besoin d'un prev maintenant parce que vous pouvez modifier directement ce que prev->next pointait vers .

pour clarifier les choses, suivons un peu le code. Pendant l'enlèvement:

  1. si entry == *head : il sera *head (==*curr) = *head->next -- head pointe maintenant au nouveau noeud de Cap. Vous faites cela en modifiant directement head contient un nouveau pointeur.
  2. si entry != *head : de même, *curr est ce que prev->next pointait, et maintenant pointe vers entry->next .

peu importe dans quel cas, vous pouvez réorganiser les pointeurs d'une manière unifiée avec des pointeurs doubles.

17
répondu ziyuang 2014-08-28 13:00:27

pointeurs à pointeurs viennent aussi à portée de main comme "poignées" à la mémoire où vous voulez passer autour d'une "poignée" entre les fonctions pour la mémoire re-localisable. Cela signifie essentiellement que la fonction peut changer la mémoire qui est pointée par le pointeur à l'intérieur de la variable de la poignée, et chaque fonction ou objet qui utilise la poignée pointera correctement vers la mémoire nouvellement déplacée (ou allouée). Les bibliothèques aiment-faire cela avec des types de données" opaques", c'est-à-dire des types de données que vous ne connaissez pas avoir à se soucier de ce qu'ils font avec la mémoire étant pointé faire, vous passez simplement la "poignée" entre les fonctions de la bibliothèque pour effectuer certaines opérations sur cette mémoire ... les fonctions de la bibliothèque peuvent allouer et dé-allouer la mémoire sous la hotte sans que vous ayez à vous soucier explicitement du processus de gestion de la mémoire ou de l'endroit où la poignée pointe.

par exemple:

#include <stdlib.h>

typedef unsigned char** handle_type;

//some data_structure that the library functions would work with
typedef struct 
{
    int data_a;
    int data_b;
    int data_c;
} LIB_OBJECT;

handle_type lib_create_handle()
{
    //initialize the handle with some memory that points to and array of 10 LIB_OBJECTs
    handle_type handle = malloc(sizeof(handle_type));
    *handle = malloc(sizeof(LIB_OBJECT) * 10);

    return handle;
}

void lib_func_a(handle_type handle) { /*does something with array of LIB_OBJECTs*/ }

void lib_func_b(handle_type handle)
{
    //does something that takes input LIB_OBJECTs and makes more of them, so has to
    //reallocate memory for the new objects that will be created

    //first re-allocate the memory somewhere else with more slots, but don't destroy the
    //currently allocated slots
    *handle = realloc(*handle, sizeof(LIB_OBJECT) * 20);

    //...do some operation on the new memory and return
}

void lib_func_c(handle_type handle) { /*does something else to array of LIB_OBJECTs*/ }

void lib_free_handle(handle_type handle) 
{
    free(*handle);
    free(handle); 
}


int main()
{
    //create a "handle" to some memory that the library functions can use
    handle_type my_handle = lib_create_handle();

    //do something with that memory
    lib_func_a(my_handle);

    //do something else with the handle that will make it point somewhere else
    //but that's invisible to us from the standpoint of the calling the function and
    //working with the handle
    lib_func_b(my_handle); 

    //do something with new memory chunk, but you don't have to think about the fact
    //that the memory has moved under the hood ... it's still pointed to by the "handle"
    lib_func_c(my_handle);

    //deallocate the handle
    lib_free_handle(my_handle);

    return 0;
}

Espère que cette aide,

Jason

12
répondu Jason 2011-04-07 14:52:24

les cordes sont un bon exemple d'utilisation de double pointeurs. La corde elle-même est un pointeur, donc chaque fois que vous avez besoin de pointer vers une corde, vous aurez besoin d'un double pointeur.

4
répondu drysdam 2011-04-07 12:13:03

La suite est très simple, C++ exemple qui montre que si vous voulez utiliser une fonction pour définir un pointeur sur un objet, vous avez besoin d'un pointeur vers un pointeur . Sinon, le pointeur va revenir à null .

(C++ réponse, mais je crois que c'est la même chose dans C.)

(aussi, pour référence: Google ("passer par la valeur c++") = " par défaut, les arguments en C++ sont passés par la valeur. Lorsqu'un argument est passé par valeur, l'argument de la valeur est copiée dans le paramètre de la fonction.")

donc nous voulons mettre le pointeur b égal à la chaîne a .

#include <iostream>
#include <string>

void Function_1(std::string* a, std::string* b) {
  b = a;
  std::cout << (b == nullptr);  // False
}

void Function_2(std::string* a, std::string** b) {
  *b = a;
  std::cout << (b == nullptr);  // False
}

int main() {
  std::string a("Hello!");
  std::string* b(nullptr);
  std::cout << (b == nullptr);  // True

  Function_1(&a, b);
  std::cout << (b == nullptr);  // True

  Function_2(&a, &b);
  std::cout << (b == nullptr);  // False
}

// Output: 10100

que se passe-t-il à la ligne Function_1(&a, b); ?

  • La "valeur" de &main::a (une adresse) est copiée dans le paramètre std::string* Function_1::a . Par conséquent Function_1::a est un pointeur vers (i.e. la mémoire adresse de) la chaîne main::a .

  • La "valeur" de main::b (une adresse en mémoire) est copiée dans le paramètre std::string* Function_1::b . Par conséquent, il y a maintenant 2 de ces adresses en mémoire, les deux pointeurs null. À la ligne b = a; , la variable locale Function_1::b est alors remplacée par la variable égale Function_1::a (= &main::a ), mais la variable main::b reste inchangée. Après l'appel à Function_1 , main::b est toujours null pointeur.

que se passe-t-il à la ligne Function_2(&a, &b); ?

  • le traitement de la variable a est le même: dans la fonction, Function_2::a est l'adresse de la chaîne main::a .

  • mais la variable b est maintenant passée en pointeur à un pointeur. La "valeur" de &main::b (l'adresse de la pointeur main::b ) est copié dans std::string** Function_2::b . Par conséquent, dans Function_2, le déréférencement de ceci comme *Function_2::b va accéder et modifier main::b . Donc la ligne *b = a; est en fait en train de définir main::b (une adresse) égale à Function_2::a (=adresse de main::a ) ce qui est ce que nous voulons.

Si vous voulez utiliser une fonction pour modifier une chose, un objet ou une adresse (pointeur), vous avez pour passe en pointeur sur ce truc. la chose que vous effectivement passez ne peut pas être modifiée (dans le champ d'application de l'appel) parce qu'une copie locale est faite.

(une exception est prévue si le paramètre est une référence, telle que std::string& a . Mais généralement ce sont const . Généralement, si vous appelez f(x) , si x est un objet, vous devriez être en mesure de supposer que f ne sera pas modifier x . Mais si x est un pointeur, alors vous devez en déduire que f pourrait modifier l'objet pointé par x .)

4
répondu jt117 2017-02-23 01:13:30

exemple Simple que vous avez probablement vu plusieurs fois avant

int main(int argc, char **argv)

dans le second paramètre vous l'avez: pointer vers pointer vers char.

notez que la notation du pointeur ( char* c ) et la notation du tableau ( char c[] ) sont interchangeables dans les arguments de fonction. Donc vous pouvez aussi écrire char *argv[] . En d'autres termes char *argv[] et char **argv sont interchangeables.

ce que représente ce qui précède est en fait un tableau de séquences de caractères (les arguments de ligne de commande qui sont donnés à un programme au démarrage).

Voir aussi cette réponse pour plus de détails sur la fonction ci-dessus signature.

4
répondu plats1 2017-09-14 11:15:07

par exemple, vous pourriez vouloir vous assurer que lorsque vous libérez la mémoire de quelque chose vous mettez le pointeur à nul par la suite.

void safeFree(void** memory) {
    if (*memory) {
        free(*memory);
        *memory = NULL;
    }
}

Lorsque vous appelez cette fonction vous souhaitez appeler avec l'adresse d'un pointeur

void* myMemory = someCrazyFunctionThatAllocatesMemory();
safeFree(&myMemory);

maintenant myMemory est défini à NULL et toute tentative de le réutiliser sera très évidemment erronée.

3
répondu Jeff Foster 2011-04-07 12:13:22

par exemple si vous voulez un accès aléatoire à des données non confidentielles.

p -> [p0, p1, p2, ...]  
p0 -> data1
p1 -> data2

- C

T ** p = (T **) malloc(sizeof(T*) * n);
p[0] = (T*) malloc(sizeof(T));
p[1] = (T*) malloc(sizeof(T));

Vous stocker un pointeur p qui pointe vers un tableau de pointeurs. Chaque pointeur pointe vers une donnée.

si sizeof(T) est grand, il ne sera peut-être pas possible d'attribuer un bloc contigu (c.-à-d. en utilisant malloc) de sizeof(T) * n octets.

2
répondu log0 2011-04-07 12:23:41

une chose que je les utilise constamment est quand j'ai un tableau d'objets et je dois effectuer des recherches (recherche binaire) sur eux par différents champs.

Je garde le tableau d'origine...

int num_objects;
OBJECT *original_array = malloc(sizeof(OBJECT)*num_objects);

Ensuite faites un tableau de pointeurs triés vers les objets.

int compare_object_by_name( const void *v1, const void *v2 ) {
  OBJECT *o1 = *(OBJECT **)v1;
  OBJECT *o2 = *(OBJECT **)v2;
  return (strcmp(o1->name, o2->name);
}

OBJECT **object_ptrs_by_name = malloc(sizeof(OBJECT *)*num_objects);
  int i = 0;
  for( ; i<num_objects; i++)
    object_ptrs_by_name[i] = original_array+i;
  qsort(object_ptrs_by_name, num_objects, sizeof(OBJECT *), compare_object_by_name);

vous pouvez faire autant de tableaux de pointeur triés que vous avez besoin, puis utiliser une recherche binaire sur le tableau de pointeur trié pour accéder à l'objet dont vous avez besoin par le les données que vous avez. Le tableau original des objets peut rester non trié, mais chaque tableau pointeur sera trié par leur champ spécifié.

2
répondu DavidMFrey 2011-04-07 13:41:37

comme dit l'une des applications de double pointeur est de mettre à jour la chaîne de façon à ce que les changements effectués soient reflétés en arrière.

#include <iostream>
#include <cstring>  // for using strcpy
using namespace std;

void change(char **temp)
{
   strcpy(temp[0],"new");
   strcpy(temp[1],"value");
}

int main()
{
   char **str;
   str = (char **)malloc(sizeof(char *)*3);
   str[0]=(char *)malloc(10);
   str[1]=(char *)malloc(10);
   strcpy(str[0],"old");
   strcpy(str[1],"name");
   char **temp = str;  // always use the temporary variable
   while(*temp!=NULL)
{
    cout<<*temp<<endl;
    temp++;
}
temp = str;   // making it point it to the original head because we have changed the address in while loop above
change(str);
while(*temp!=NULL)
{
   cout<<*temp<<endl;
   temp++;
}

free(temp);
free(str[0]);
free(str[1]);
free(str);
2
répondu Abhishek Karigar 2018-06-26 20:33:28

j'ai utilisé des pointeurs doubles aujourd'hui pendant que je programmais quelque chose pour le travail, donc je peux répondre pourquoi nous avons dû les utiliser (c'est la première fois que j'ai dû en fait utiliser des pointeurs doubles). Nous avons dû nous occuper de l'encodage en temps réel des images contenues dans les tampons qui sont membres de certaines structures. Dans l'encodeur, nous devions utiliser un pointeur vers l'une de ces structures. Le problème était que notre pointeur était changé pour pointer vers d'autres structures d'un autre fil. Pour utiliser le courant structure dans le codeur, j'ai dû utiliser un double pointeur, afin de pointer le pointeur a été modifié dans un autre thread. Il n'était pas évident au début, du moins pour nous, que nous devions adopter cette approche. Beaucoup d'adresse ont été imprimés dans le processus :)).

vous devez utiliser des pointeurs doubles lorsque vous travaillez sur des pointeurs qui sont changés dans d'autres endroits de votre application. Vous pourriez également trouver des pointeurs doubles à être un must lorsque vous traitez avec le matériel qui retourne et adresse à vous.

1
répondu Axenie Ionut 2014-11-11 17:06:43

pourquoi deux pointes?

l'objectif est de changer ce que studentA pointe, en utilisant une fonction.

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


typedef struct Person{
    char * name;
} Person; 

/**
 * we need a ponter to a pointer, example: &studentA
 */
void change(Person ** x, Person * y){
    *x = y; // since x is a pointer to a pointer, we access its value: a pointer to a Person struct.
}

void dontChange(Person * x, Person * y){
    x = y;
}

int main()
{

    Person * studentA = (Person *)malloc(sizeof(Person));
    studentA->name = "brian";

    Person * studentB = (Person *)malloc(sizeof(Person));
    studentB->name = "erich";

    /**
     * we could have done the job as simple as this!
     * but we need more work if we want to use a function to do the job!
     */
    // studentA = studentB;

    printf("1. studentA = %s (not changed)\n", studentA->name);

    dontChange(studentA, studentB);
    printf("2. studentA = %s (not changed)\n", studentA->name);

    change(&studentA, studentB);
    printf("3. studentA = %s (changed!)\n", studentA->name);

    return 0;
}

/**
 * OUTPUT:
 * 1. studentA = brian (not changed)
 * 2. studentA = brian (not changed)
 * 3. studentA = erich (changed!)
 */
1
répondu Brian Joseph Spinos 2016-11-26 23:54:46

espérons que l'exemple suivant clarifiera certains concepts concernant les pointeurs et les pointeurs doubles , leurs différences et leur utilisation dans des scénarios communs.

    int* setptr(int *x)
    {
        printf("%u\n",&x);
        x=malloc(sizeof(int));
        *x=1;
        return x;
    }

In the above function setptr we can manipulate x either
1. by taking fn arg as int *x , doing  malloc and setting value of x and return x 
Or
    2. By taking arg as int ** and malloc and then set  **x value to some value.
Note: we cant set any general pointer directly without doing  malloc.Pointer indicates that it is a type of variable which can hold address of any data type.Now either we define a variable and give reference to it or we declare a pointer(int *x=NULL) and allocate some memory to it inside the called function where we pass x or a reference to it .. In either case we need to have address of a memory in the  pointer and in the case pointer initially points  to NULL or it is defined like int *x where it points  to any random address then we need to assign a valid memory address to pointer 

    1. either we need to allocate memory to it by malloc

    int *x=NULL means its address is 0.
    Now we need to either o following
    1.



    void main()
        {
            int *x;
            x=malloc
            *x=some_val;
        }
        Or
        void main()
        {
            int *x
            Fn(x);
        }

        void Fn(int **x)
        {
            *x=malloc;
            **x=5;
        }
        OR
        int * Fn(int *x)
        {
            x=malloc();
            *x=4;
            Return x;
        }


        2. Or we need to point it to a valid memory like a defined variable inside the function where pointer is defined.


        OR
        int main()
        {
            int a;
            int *x=&a;
            Fn(x);
            printf("%d",*x);
        }
        void Fn(int *x)
        {
            *x=2;
        }


     in both cases value pointed by x is changed inside fn

    But suppose if we do like


    int main()
    {
        int *x=NULL;
        printf("%u\n",sizeof(x));
        printf("%u\n",&x);
        x=setptr(x);
        //*x=2;
        printf("%d\n",*x);
        return 0;
    }

/* output
4
1
*/

#include<stdio.h>
void setptr(int *x)
{
    printf("inside setptr\n");
    printf("x=%u\n",x);
    printf("&x=%u\n",&x);
    //x=malloc(sizeof(int));
    *x=1;
    //return x;
}
int main()
{
    int *x=NULL;
    printf("x=%u\n",x);
    printf("&x=%u\n",&x);
    int a;
    x=&a;
    printf("x=%u\n",x);
    printf("&a=%u\n",&a);
    printf("&x=%u\n",&x);
    setptr(x);
    printf("inside main again\n");

    //*x=2;
    printf("x=%u\n",x);
    printf("&x=%u\n",&x);
    printf("*x=%d\n",*x);
    printf("a=%d\n",a);
    return 0;
}
0
répondu Peter_pk 2015-04-27 01:51:07

application de double pointeur comme indiqué par Bhavuk Mathur semble être erroné. Voici l'exemple suivant est celui valide

void func(char **str)
{
     strcpy(str[0],"second");
}

int main(){

    char **str;
    str = (char **)malloc(sizeof(char*)*1); // allocate 1 char* or string
    str[0] = (char *)malloc(sizeof(char)*10);      // allocate 10 character
    strcpy(str[0],"first");            // assign the string
    printf("%s\n",*str);
    func(str);            
    printf("%s\n",*str);           
    free(str[0]); 
    free(str);
}
0
répondu Abhishek Karigar 2018-06-24 15:50:43

l'exemple suivant, que je donne donnera un aperçu ou une intuition sur la façon dont double pointeurs fonctionnent, je vais passer par les étapes

1) try to understand the following statements
   char **str ;

   a) str is of type char ** whose value is an address of another pointer.
   b) *str is of type char * whose value is an address of variable or (it is a string itself).
   c) **str is of type char ,gives the value stored, in this case a character.

ce qui suit est le code auquel vous pouvez vous rapporter aux points ci-dessus(a,b,C) pour comprendre

str = (char **)malloc(sizeof(char *) *2); // here i am assigning the mem for two char *
       str[0]=(char *)"abcdefghij"; // assignin the value
       str[1]=(char *)"xyzlmnopqr"; 

maintenant pour imprimer la valeur I. les chaînes e dans le tableau, regardez le point b, En cas de chaîne de caractères, la valeur ainsi que l'adresse sont identiques, de sorte qu'il n'est pas nécessaire de la déréférencer à nouveau.

cout<<*str<<endl;   // abcdefghij;

pour imprimer la chaîne suivante, sortez d'une dereference I. e ( * ) de * str à str et ensuite incrémenter, comme indiqué ci-dessous

str++;

maintenant, imprimez la chaîne

cout<<*str<<endl;        //xyzlmnopqr

pour imprimer uniquement des caractères dans une chaîne de caractères, se référer au point c)

cout<<**str<<endl;  // prints the first character i.e "a"

maintenant pour imprimer le prochain caractère d'une chaîne I. e " b" sortir de 1 opérateur dereference et l'incrémenter I. e passer de * * str à * str Et do * str++

*str++;

maintenant, imprimez le caractère

cout<<**str<<endl;  // prints the second character i.e "b"

puisque les deux tableaux ("abcdefghij", "xylmnopqr") sont stockés dans un bloc continu de mémoire si la même chose est faite d'incrémenter l'adresse, tous les caractères de deux chaînes seront imprimés

0
répondu Abhishek Karigar 2018-06-25 11:40:59