请耐心等待我,我来自其他语言和新手,并从http://c.learncodethehardway.org/book/learn-c-the-hard-way.html
学习struct Person {
char *name;
int age;
int height;
int weight;
};
struct Person *Person_create(char *name, int age, int height, int weight)
{
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who->name = strdup(name);
who->age = age;
who->height = height;
who->weight = weight;
return who;
}
我理解第二个Person_create函数返回struct Person的指针。我不明白是(可能是因为我来自其他语言,erlang,ruby),为什么将其定义为
struct Person *Person_create(char *name, int age, int height, int weight)
不是
struct Person Person_create(char *name, int age, int height, int weight)
还有其他方法来定义一个返回结构的函数吗?
抱歉,如果这个问题太基础了。答案 0 :(得分:11)
它的定义是因为它返回一个指向结构的指针,而不是结构。您将返回值分配给struct Person *
,而不是struct Person
。
可以返回完整的结构,如:
struct Person Person_create(char *name, int age, int height, int weight)
{
struct Person who;
who.name = strdup(name);
who.age = age;
who.height = height;
who.weight = weight;
return who;
}
但它并不经常使用。
答案 1 :(得分:3)
该函数返回who
,它是struct Person *
- 指向结构的指针。保存结构的内存由malloc()
分配,函数返回指向该内存的指针。
如果声明函数返回struct Person
而不是指针,则who
也可以声明为结构。返回后,结构将被复制并返回给调用者。请注意,复制的效率低于仅仅返回指向内存的指针。
答案 2 :(得分:3)
Person_create
函数返回指向struct Person
的指针,因此您必须将返回值定义为指针(通过添加*)。要理解返回指向结构而不是结构本身的指针的原因,必须理解C处理内存的方式。
在C中调用函数时,在call stack上为其添加记录。在调用堆栈的底部是您正在运行的程序的main
函数,顶部是当前正在执行的函数。堆栈中的记录包含诸如传递给函数的参数值和函数的所有局部变量之类的信息。
您的程序可以访问另一种类型的内存:堆内存。这是使用malloc
分配空间的地方,它没有连接到调用堆栈。
当您从函数返回时,将弹出调用堆栈,并且与函数调用关联的所有信息都将丢失。如果要返回结构,则有两个选项:在从调用堆栈中弹出结构之前复制结构内的数据,或者将数据保存在堆内存中并返回指向它的指针。复制数据字节的字节比仅返回指针要昂贵,因此通常需要这样做以节省资源(内存和CPU周期)。但是,它并非没有成本;当你将数据保存在堆内存中时,你必须记住当你停止使用它时{} {}},否则你的程序会泄漏内存。
答案 3 :(得分:2)
默认情况下,C / C ++中的结构不是指针(或引用),因为它们例如在Java中。结构人函数()因此返回结构本身(通过值,制作副本)而不是指针。
您通常不希望创建对象的副本(默认情况下为浅副本,或使用复制构造函数创建的副本),因为这很快就会非常耗时。
答案 4 :(得分:1)
复制整个结构而不仅仅是指针的效率较低,因为指针的sizeof
通常远小于整个结构本身的sizeof
。
此外,结构可能包含指向内存中其他数据的指针,盲目复制可能对动态分配的数据很危险(如果处理一个副本的代码将释放它,另一个副本将留下无效指针)。
如此浅的副本几乎总是一个坏主意,除非你确定原文超出了范围 - 然后你为什么不直接返回指向结构的指针(当然在堆上动态分配的结构) ,因此在从函数返回时,它不会像堆栈分配的实体一样被销毁。