今天我在教几个朋友如何使用C结构体。其中一个问你是否可以从函数返回结构体,我回答说:“不能!你会返回指向动态错误结构的指针。”
来自一个主要做c++的人,我期望不能按值返回结构。在c++中,你可以重载对象的操作符=,使用函数按值返回对象是完全有意义的。然而,在C语言中,你没有这个选项,所以它让我思考编译器实际上在做什么。考虑以下几点:
struct MyObj{
double x, y;
};
struct MyObj foo(){
struct MyObj a;
a.x = 10;
a.y = 10;
return a;
}
int main () {
struct MyObj a;
a = foo(); // This DOES work
struct b = a; // This does not work
return 0;
}
我明白为什么struct b = a;不应该工作——您不能重载数据类型的operator =。为什么a = foo();编译好了吗?它的意思是不是不是struct b = a;?也许要问的问题是:结合=符号的return语句到底有什么作用?
回传结构体没有问题。它将通过值传递
但是,如果结构体包含任何具有局部变量地址的成员呢
struct emp {
int id;
char *name;
};
struct emp get() {
char *name = "John";
struct emp e1 = {100, name};
return (e1);
}
int main() {
struct emp e2 = get();
printf("%s\n", e2.name);
}
现在,这里的e1.name包含函数get()的本地内存地址。
一旦get()返回,name的本地地址将被释放。
因此,在调用者中,如果我们试图访问该地址,它可能会导致分割错误,因为我们正在尝试一个释放的地址。这很糟糕。
这里是e1。Id将完全有效,因为它的值将被复制到e2.id
因此,我们应该总是尽量避免返回函数的本地内存地址。
任何错误的东西都可以在需要的时候返回
#include <stdio.h>
struct emp {
int id;
char *name; /* This must point to valid memory, or replace with an array that holes the data, like this char name[128] */
};
struct emp bad() {
static char name[] = {'J', 'o', 'h', 'n', '\0'}; /* static enforces this array to be stored globally and not in the local stack which would not be valid after the function returns */
struct emp e1 = {404, name};
return (e1);
}
int main() {
struct emp e2 = bad();
printf("%s\n", e2.name);
}