2009-08-19 15 views
5

Pensé que entendía los conceptos básicos de los punteros, pero después de revisar algo de documentación sobre algunos métodos sqlite3 me lanzaron, por lo que ahora no estoy seguro si mi comprensión es correcta.Necesito una explicación de cómo funcionan los punteros al pasar como función args

Aquí es una llamada a un método de sqlite3:

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

Y aquí es la declaración cabecera de la función:

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

Por qué es que & base de datos de repente se convierte en un puntero a un puntero?

Otra llamada a un método para cerrar la conexión de la base de datos es: sqlite3_close (base de datos);

con los siguientes en la cabecera de la función:

int sqlite3_close(sqlite3 *); 

¿Por qué es esto sólo un puntero, cuando paso en un puntero? ¿No sería esto un puntero a un puntero?

De todos los ejemplos que he visto siempre me pareció el inverso de las funciones anteriores, es decir.

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

// function call 
foo(&bar); 

Gracias por la ayuda.

+1

Espera, ¿estás preguntando por qué se usó un puntero doble o cómo funcionan los parámetros? – Sean

+0

Supongo un poco de ambos. – chris

+0

Erm, ¿cómo se declara la base de datos? – amaterasu

Respuesta

15

Lo más probable es que sqlite3_open asigne memoria para el manejador de la base de datos. Por esta razón, la función necesita un puntero a un puntero al mango de base de datos (sqlite3) para que se pueda modificar el puntero al mango de base de datos. Por ejemplo:

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

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

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

    /* ... */ 
    return 0; 
} 

Sin embargo, sqlite3_close sólo se necesita un único puntero a la memoria free:

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

    free(pDb); 

    return 0; 
} 
+0

no es probable, exactamente eso! –

+0

Gracias por la explicación en el primer ejemplo. Eso tiene perfecto sentido. En cuanto al segundo fragmento de código, siempre pensé que cuando una función requiere un puntero, debe pasarle la dirección variable, es decir, var, pero supongo que es incorrecta. – chris

+0

Solo es incorrecto si "var" es un valor. Si ya tiene un puntero, puede pasarlo tal como está. – Sean

4

Un puntero es la dirección de una variable.

Suponiendo que database se declara como sqlite3* database;, &database es la dirección (o, un puntero a) el puntero database.

sqlite3_open toma un puntero a un puntero para que pueda establecer el valor al que apunta el puntero. Realiza un valor de sqlite y cambia el puntero para que apunte a él. sqlite3_close no cambia a lo que apunta el puntero, por lo que todo lo que necesita es el puntero en sí.

5

creo que la breve explicación de lo que está pidiendo es que el uso de "&" esencialmente significa "un puntero a esta"

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

No sabía que pudieras hacer lo que hiciste en la tercera línea. Aunque no entiendo qué está pasando exactamente con respecto a las direcciones de las memes, sí explica el método sqlite3_open. – chris

+0

Cuando se declara "value", la memoria se reserva para ese int. When " puntero "se declara, la memoria se reserva para int * y se mantiene en la dirección de" valor ". Cuando se declara" doublePointer ", está asignando la dirección de cualquier memoria que se haya reservado para" puntero ". – Sean

0

no sé qué quiere hacer con la función sqlite. Pero el uso de punteros te hace mantener los cambios en las funciones.

Cuando pasa una variable a una función, la variable se duplicará.

por ejemplo

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

el valor de var1 = 5

la dirección de var1 = 0xff2200 (algo así)

el valor de ptr1 = 0xff2200 (la dirección de var1)

la dirección de ptr1 = 0xff0022 (algo diferente)

Le permite escribir una función que utiliza estos dos var como arg

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

después de u utilizar esta función;

func(var1, ptr1); 

var1 no será igual a 0 !!! Será -5

Porque; en función func1

el valor de x = 0 (el valor de var1)

la dirección de x = 0xaabbcc (algo distinto, entonces var1 !!! esta es la razón por x + = 5 no es efectiva en var1. esto sucede en otra parte de la memoria! Cuando la vuelta de u, esta memoria será libre de nuevo. Y si no se pierden los cambios ...)

la dirección de p = 0xCCCCCC (algo diferente también)

la valor de p = 0xff2200 (el valor de ptr1 y la dirección de var1! Esta operación se realizará en la dirección var1 para que no pierda su chan ges)

Si tenemos que mantener nuestros cambios de variables -en funciones-, tenemos que usar punteros para esas var. Si nuestra variable guarda una dirección, significa; es un puntero. Y si queremos mantener los cambios de puntero -en funciones- entonces tenemos que usar puntero a puntero.

Este es mi primer mensaje y espero que esto será servicial ...

Y "el paso por referencia" significa "pasar" puntero otros idiomas no utilice punteros. así que tienes que pasar por referencia a veces. Pero en C, los punteros harán su trabajo ...

Cuestiones relacionadas