5 votes

Besoin d'une explication sur le fonctionnement des pointeurs lorsqu'ils sont passés en tant qu'arguments de fonction.

Je pensais avoir compris les bases des pointeurs, mais après avoir vérifié la documentation de certaines méthodes de sqlite3, j'ai été déstabilisé, et maintenant je ne suis pas sûr que ma compréhension soit correcte.

Voici un appel à une méthode sqlite3 :

char* dataFilePath = "foobar.sqlite";
if (sqlite3_open(dataFilePath, &database) != SQLITE_OK) {...}   

Et voici la déclaration de l'en-tête de la fonction :

int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);

Comment se fait-il que &database devienne soudainement un pointeur sur un pointeur ?

Un autre appel de méthode pour fermer la connexion à la base de données est : sqlite3_close(database) ;

Avec ce qui suit à l'en-tête de la fonction :

int sqlite3_close(sqlite3 *);

Pourquoi est-ce que c'est juste un pointeur, quand je passe dans un pointeur ? Ne s'agit-il pas d'un pointeur vers un pointeur ?

D'après tous les exemples que j'ai vus, il semble que ce soit toujours l'inverse des fonctions ci-dessus, c'est-à-dire

// function
void foo(someDataType *bar) { ... }

// function call
foo(&bar);

Merci pour votre aide.

15voto

Andrew Keeton Points 6268

Très probablement, sqlite3_open alloue de la mémoire pour l'identifiant de la base de données. Pour cette raison, la fonction a besoin d'un pointeur vers un pointeur à l'identifiant de la base de données ( sqlite3 ) afin qu'il puisse modifier le pointeur à l'identifiant de la base de données. Par exemple :

typedef struct { /*...*/ } sqlite3;

int sqlite3_open(const char *filename, sqlite3 **ppDb) {
    /* ... */

    // Allocate memory for the database handle.
    *ppDb = (sqlite3 *)malloc(sizeof(sqlite3));

    /* ... */
    return 0;
}

Cependant, sqlite3_close n'a besoin que d'un seul pointeur vers free la mémoire :

int sqlite3_close(sqlite3 *pDb) {
    /* ... Cleanup stuff ... */

    free(pDb);

    return 0;
}

5voto

Sean Points 446

Je pense que l'explication courte de ce que vous demandez est que l'utilisation de "&" signifie essentiellement "un pointeur vers ceci".

int value = 0;
int *pointer = &value;
int **doublePointer = &pointer;

4voto

SLaks Points 391154

Un pointeur est l'adresse d'une variable.

En supposant que database est déclaré comme sqlite3* database; , &database est l'adresse (ou un pointeur) de l'objet database pointeur.

sqlite3_open prend un pointeur sur un pointeur afin de pouvoir définir la valeur sur laquelle pointe le pointeur. Il fait un sqlite et modifie votre pointeur pour qu'il pointe vers cette valeur. sqlite3_close ne change pas ce vers quoi le pointeur pointe, donc tout ce dont il a besoin est le pointeur lui-même.

0voto

Sinan Ünür Points 76179

0voto

H2O Points 186

Je ne sais pas ce que vous voulez faire avec la fonction sqlite. Mais l'utilisation de pointeurs vous oblige à garder les changements dans les fonctions.

Lorsque vous passez une variable à une fonction, la variable sera dupliquée.

par exemple

int var1=0;
in *ptr1=&var1;
func(var1, ptr1);

la valeur de var1=5

l'adresse de var1 = 0xff2200 (quelque chose comme ça)

la valeur de ptr1 = 0xff2200 (l'adresse de var1)

l'adresse de ptr1 = 0xff0022 (quelque chose de différent)

Écrivons une fonction qui utilise ces deux variables comme argument.

void func1(int x, int *p){
    x+=5;
    (*p)-=5;
}

après avoir utilisé cette fonction ;

func(var1, ptr1);

var1 ne sera pas égal à 0 !!! İt sera -5

Parce que ; dans la fonction func1

la valeur de x = 0 (la valeur de var1)

l'adresse de x = 0xaabbcc (quelque chose de différent de la var1 !!! c'est pourquoi x+=5 n'est pas effectif sur la var1. Cela se passe dans une autre partie de la mémoire ! Quand tu reviendras, cette mémoire sera à nouveau libre. Et vous perdrez vos modifications...)

l'adresse de p = 0xcccccc (quelque chose de différent aussi)

la valeur de p = 0xff2200 (la valeur de ptr1 et l'adresse de la var1 ! Cette opération se fera dans l'adresse de var1 pour ne pas perdre vos modifications).

Si nous devons garder nos changements de variables -dans les fonctions-, nous devons utiliser des pointeurs pour ces variables. Si notre variable garde une adresse, cela signifie que c'est un pointeur. Et si nous voulons garder les changements de pointeur -dans les fonctions- alors nous devons utiliser des pointeurs vers les pointeurs.

C'est mon premier message et j'espère qu'il sera utile...

Et "passer par référence" signifie "passer par pointeur". D'autres langages n'utilisent pas de pointeurs, donc vous devez parfois passer par référence. Mais en C, les pointeurs feront leur travail...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X