1

我在代码的几乎每个部分都看到了以下初始化本地指针的方法。想了解这样做的原因和复杂性。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initialize_p(char **p)
{
        char *p_local = NULL;
        p_local=malloc(6);
        strcpy(p_local,"sandy");
        *p = p_local;
}
int main(void)
{
        char *p = NULL;
        initialize_p(&p);
        printf("Name : %s\n",p);
        return 0;
}

就是这样,我在这里用简单的字符串显示。在我的实际代码中,它是使用结构完成的。

我有点理解上述逻辑,但我也不明白。请明确上述实现方式所涉及的概念。另外,让我知道是否有其他更好的方法可以做到这一点。

请赐教.. :)

4

5 回答 5

4

我可能会返回新分配的字符串,而不是将指针作为参数传递给指针:

char *initialize(void) {
    char *init = "sandy"; 
    char *ret = malloc(sizeof(init)+1);
    if (ret != NULL)
        strcpy(ret, init);
    return ret;
}

int main() {
    char *p = initialize();
    printf("Name: %s\n", p);
    free(p);
    return 0;
}
于 2012-08-16T04:48:30.323 回答
0

这是一个外参数。该函数为您生成结果,并将其保存到您传递的参数中。当结果的大小可能不同时,或者如果参数的类型是不透明的,这通常使用。

就个人而言,我认为返回结果更加清晰,并且在需要动态分配时不易出错(如 JerryCoffin 的答案 +1 所示)。

当不需要动态分配时,如果它不是非常小,则通过引用(作为非常量参数)传递它:

struct t_struct { int a[100]; };

void InitStruct(struct t_struct* pStruct) {
  pStruct->a[0] = 11;
  ...
}

struct t_struct s;
void InitStruct(&s);

如果它很小,您可以考虑按值返回。

于 2012-08-16T04:53:46.160 回答
0

在 initialize_p 中分配了一块内存,并将一些字符串复制到内存中。为了让初始化程序的调用者获得这个新内存块的地址,指针 p 的地址被传递给 initialize_p:

    char **p

         +---+---+---+---+---+----+
   *p -> | s | a | n | d | y | \0 |
         +---+---+---+---+---+----+

如果只有 *p 会被传递,那么在函数内部设置指针将相当于:

void foo(int a)
{
  a=3;
  ...
}

更好的方法是使用 strdup ,它与您在函数中所做的事情相同

char* initialize_p()
{
   return strdup("sandy");
}

还要确保释放返回的字符串以避免内存泄漏。

于 2012-08-16T04:53:59.797 回答
0

我建议你创建分配和释放函数对

char *createP()
{
    char *p = NULL;
    p=malloc(6);
    strcpy(p,"sandy");
    return p;
}
void freeP(char *p)
{
    if (p) free(p);
}
int main(void)
{
    char *p = createP();
    printf("Name : %s\n",p);
    freeP(p);
    return 0;
}
于 2012-08-16T04:57:12.717 回答
0

清除概念?好吧,在这样一个简单的情况下,我看不出使用 byref 输出参数进行操作的意义——对我来说,如果像这样工作,则类似面向对象的结构构造函数更容易理解:

struct foo *bar = myobj_new(); // uses malloc and returns a pointer
// do something with bar
myobj_destroy(bar); // uses free

有些人同意这种设计很好,因为函数的返回值可以用作错误/成功代码(你见过 SQLite3 吗?),但我不同意。我认为函数的主要、最重要的结果应该通过返回值,而不是一些辅助的东西。(我倾向于编写通过返回 NULL 并设置 byref-passed 错误代码来指示失败的库)。

我能想到的唯一有效场景是传递这样的参数更合乎逻辑或更对称。例如,想象一个非常奇怪的排序函数,它类似于 C 标准库函数qsort(),但需要它的比较函数本身来在需要时交换两个元素。比较函数显然需要通过 byref 访问它的两个参数以便交换它们,但将最初遇到的顺序返回给调用方排序函数以优化算法也可能很有用。所以这个比较函数可能是这样的:

int compare(void *a, void *b)
{
    int x = *(int *)a;
    int y = *(int *)b;

    if (x > y)
    {
        *(int *)a = y;
        *(int *)b = x;
        return +1;
    } else if (x < x) {
        return -1;
    }

    return 0;
}

嗯,关于我的看法,差不多就这些了……

于 2012-08-16T04:58:27.430 回答