从C函数返回指针是好/坏设计?

我想知道来自C函数的返回指针是好/坏设计? 如果这是一个不好的做法,在下面的例子中,这将是一个好习惯:

问题是继续部分: c函数返回静态变量

data.h文件中:

 #include  #include  typedef struct { int age; int number; } person; person * getPersonInfo(); 

data.c

 #include "data.h" static struct person* person_p = NULL; person * getPersonInfo() { person_p = (struct person*)malloc(10 * sizeof(struct person)); return person_p; } 

main.c

 #include "data.h" int main() { person* pointer = getPersonInfo(); return 0; } 

基本上, main文件中的main函数需要获取静态指针person_p指向的数组的所有元素的值,如果不是一个好习惯,那么应该是一个好的做法?

它不好的唯一原因是因为你背后没有任何内存管理结构。 在您当前的代码中,您有内存泄漏,因为您通过malloc()分配一个person结构,但不释放它。

考虑编写一个包装器函数,为您处理内存管理,如下所示:

 void freePerson(struct person * personToDelete) { free(personToDelete); } 

然后在你的主要:

 int main() { person* pointer = getPersonInfo(); freePerson(pointer); // After you are done using it return 0; } 

我还要警告不要转换malloc()的结果。 根据我的经验,它可能导致未定义的行为。

返回指向私有变量的指针是不好的做法。 此外,使用当前设计,您的.c文件只能有一个person对象的实例。

而且几乎不用说,动态分配对象的相同代码也应该负责释放它。 编写的代码是为了使程序中的其他模块能够清理混乱,每个设计都会导致内存泄漏。

如果您正在编写至少有些复杂的数据类型,您需要限制对私有变量的访问,拥有结构的多个实例等,那么最好使用“opaque类型”。 示例(未测试):

// data.h

 #ifndef DATA_H #define DATA_H #include  #include  typedef struct person person; // opaque type person* person_create (void); void person_delete (person* p); void person_set_age (person* p, int age); int person_get_age (const person* p); // ... and so on, setters/getters #endif // DATA_H 

// data.c

 #include "data.h" struct { int age; int number; } person; person* person_create (void) { return malloc(sizeof(struct person)); } void person_delete (person* p) { free(p); } void person_set_age (person* p, int age) { p->age = age; } int person_get_age (const person* p) { return p->age; } 

//来电者:

 #include "data.h" int main() { person* p = person_create(); person_set_age(p, 50); printf("%d", person_get_age(p)); person_delete(p); return 0; } 

有些事情需要考虑:

  • 始终在h文件中使用标题保护。
  • 切勿对C函数使用空参数列表() (但总是在C ++中使用)。
  • 不要在C中强制转换malloc的结果(但总是在C ++中)。
  • 如果malloc失败,则需要在此代码中添加一些error handling。

要成为一个好的设计,您必须具有匹配的function,以便在不再需要时释放分配的内存。

这是一个决定问题,而不是其他一切。

只要您了解每个专家和骗局,这两个选项都是有效的

返回指针优点:

  1. 封装内存分配
  2. 动态支持动态内存大小

返回指针缺点:

  1. 只有一个可能的参数
  2. 每次都必须在堆上分配内存

接受指针作为输入专业正好相反:

  1. 多个输出参数
  2. 内存不必在堆上分配,调用者可以使用其堆栈上的变量作为输出参数

接受指针作为输入缺点:

  1. 没有封装内存分配
  2. 动态内存大小不支持动态 – 大小必须固定或预先指定

在您的具体示例中,我将使用输出参数,因为它是固定大小,并且可以在不动态分配内存的情况下轻松调用。