1. 程式人生 > >在其他函式中初始化

在其他函式中初始化

當我們給指標申請記憶體空間的時候,我們正常使用下面的程式碼

char *p = NULL;
p = (char*)malloc(5);

free(p);
p = NULL;

但是我遇到的問題是,當前不知道需要分配的大小,只能把這個指標傳遞給子函式,在子函式中malloc並賦值。

於是就出現了以下的錯誤程式碼

int init_err(char *pp)
{
    pp = (char*)malloc(10);
}
int main()
{
    char *p = NULL;
    init_err(p);

    free(p);
    p = NULL;
    return 0;
}

這麼寫是錯的,此時p是空的(NULL),不能free,而且p也沒法使用。

似懂非懂,闡述一下我的想法。在init_err(char *pp)中,指標pp其實已經不是原來的p了,pp只是指向了p的地址,你給pp開闢了記憶體,跟p沒有關係。

無意間瞟了一眼sqlite3的介面,明白了,正確的程式碼應該是這樣:

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

int init(char **p)
{
    *p = (char*)malloc(10);
}

int main()
{
    char *p = NULL;
    p = (char*)malloc(5);
    p[0] = '1';
    p[1] = '1';
    p[2] = '1';
    p[3] = '1';
    p[4] = '\0';
    printf("%s\n", p);
    free(p);
    p = NULL;

    init(&p);
    p[0] = 'a';
    p[1] = 'a';
    p[2] = 'a';
    p[3] = 'a';
    p[4] = 'b';
    p[5] = 'b';
    p[6] = 'b';
    p[7] = 'b';
    p[8] = '\0';
    printf("%s\n", p);
    free(p);
    p = NULL;

    return 0;
}

中間加了一些賦值語句。用一個二級指標做形參,存放實際的p的記憶體地址。

回過頭來看寫sqlite的程式碼:

char *errmsg = NULL;
char sql[256];
char **res;
int row = 0, column = 0;

ret = sqlite3_get_table(db, sql, &res, &row, &column, &errmsg);
if (ret != SQLITE_OK)
{
    printf("sqlite err (%d): %s\n", ret, errmsg);
    sqlite3_free(errmsg);
    return CHK_ERR;
}
else
{

}
sqlite3_free_table(res);
errmsg和res在API中都是通過取地址傳遞的。