当作为函数参数传递时,指针如何工作的解释

5

我曾经认为我理解指针的基础知识,但是在查看一些sqlite3方法的文档后,我感到困惑了,现在我不确定我的理解是否正确。

这里是一个调用sqlite3方法的示例:

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

这里是函数头的声明:

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

为什么&database 突然变成了一个指向指针的指针?

关闭数据库连接的另一种方法调用是: sqlite3_close(database);

函数头如下:

int sqlite3_close(sqlite3 *);

当我传入一个指针时,为什么这只是一个指针?难道这不应该是指向指针的指针吗?

从我看到的所有示例中,它似乎总是与上面的函数相反。

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

// function call
foo(&bar);

感谢您的帮助。

1
等一下,你是在问为什么使用双指针还是参数如何工作? - Sean
数据库声明为什么了? - amaterasu
5个回答

15

很可能,sqlite3_open正在为数据库句柄分配内存。因此,该函数需要一个指向数据库句柄(sqlite3)的指针的指针,以便它可以修改指向数据库句柄的指针。例如:

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

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

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

    /* ... */
    return 0;
}

然而,sqlite3_close 只需要一个指针来 free 内存:

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

    free(pDb);

    return 0;
}

感谢第一个示例的解释。那很有道理。至于第二个代码片段,我一直认为当函数调用指针时,必须传递变量地址即&var,但我想这是不正确的。 - chris
只有当“var”是一个值时才是不正确的。如果你已经有一个指针,你可以直接传入它。 - Sean
@iso 你已经接近成功了。当一个函数的参数是指针时,它需要一个指针。无论你如何获取指针都没有关系。所以如果你有一个函数 int func(int *ip),它需要一个指向 int 的指针。无论你是给它 int x = 5; func(&x); 还是 int *ix; *ix = 5; func(ix); 都没有关系。 - Andrew Keeton
@Andrew:这样就有意义多了。谢谢。 - chris

5
我认为你所询问的简要解释是,使用"&"本质上意味着“指向此处的指针”。
int value = 0;
int *pointer = &value;
int **doublePointer = &pointer;

1
我不知道你在第三行所做的事情。虽然我不明白关于内存地址发生了什么,但它确实解释了sqlite3_open方法。 - chris
当声明"value"时,将为该int类型分配内存。 当声明"pointer"时,将为int*类型分配内存,并且它会保存"value"的地址。 当声明"doublePointer"时,您正在分配一个指向为"pointer"分配的内存地址。 - Sean

4

指针是变量的地址。

假设database被声明为sqlite3* database;&databasedatabase指针的地址(或者说是一个指向database指针的指针)。

sqlite3_open需要传递一个指向指针的指针,以便它可以设置指针所指向的值。它创建了一个sqlite值,并将您的指针更改为指向它。而sqlite3_close不会更改指针所指向的内容,因此它只需要指针本身。


0

我不知道你想用 SQLite 函数做什么。但使用指针可以让你在函数中保留更改。

当你将一个变量传递给一个函数时,该变量将被复制。

例如

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

var1的值为5

var1的地址为0xff2200(类似于这样)

ptr1的值为0xff2200(即var1的地址)

ptr1的地址为0xff0022(不同于上面的地址)

让我们编写一个函数,使用这两个变量作为参数

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

使用此函数后;

func(var1, ptr1);

var1不会等于0!!! 它将是-5

因为; 在函数func1中

x的值= 0(var1的值)

x的地址= 0xaabbcc(与var1不同的东西!!!这就是为什么x+=5对var1没有影响。它发生在内存的另一个部分!当您返回时,此内存将再次释放。然后你会失去你的更改...)

p的地址= 0xcccccc(也有所不同)

p的值= 0xff2200(ptr1的值和var1的地址!此操作将在var1的地址上执行,因此您不会失去更改)

如果我们必须在函数中保留变量的更改,则必须使用指针来引用那些变量。 如果我们的变量保留一个地址,那么它就是一个指针。如果我们想在函数中保留指针的更改,则必须使用指向指针的指针。

这是我的第一条消息,我希望这将有所帮助...

“按引用传递”意味着“按指针传递”,其他语言不使用指针。因此,有时必须通过引用传递。但在C中,指针将完成其工作...


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接