C堆/堆栈和函数返回值

时间:2014-07-15 22:20:20

标签: c

如果这是一个“基本”问题,请道歉,但我是C的新手,无法找到答案。我的问题是需要malloc变量并在函数中返回其指针,与在函数中创建变量和return结果相比。

首先想到的是,一旦函数终止,在函数范围内声明的任何变量都将被销毁;那么为什么以下是有效的:

int add(int a, int b)
{
    int result;
    result = a + b;
    return result;
}

但以下不是?

char *concat(char* a, char* b)
{
    char result[10];
    strcat(result, a);
    strcat(result, b);
    return result;
}

你得到的警告是你正在向一个局部变量返回一个地址,但这也是我们在第一个函数中所做的事情?行为是否因类型而异?

对于一个更实际的例子,我对于我应该使用以下哪两个函数感到困惑,因为它们对我的程序都非常有效:

struct Card *card_create(enum Rank rank, enum Suit suit)
{
    struct Card *card = malloc(sizeof(struct Card));
    if(card == NULL) {
        fprintf(stderr, "malloc: %s", strerror(errno));
        return NULL;
    }
    card->rank = rank;
    card->suit = suit;
    return card;
}

或者:

struct Card card_create(enum Rank rank, enum Suit suit)
{
    struct Card card;
    card.rank = rank;
    card.suit = suit;
    return card;
}

再次,对不起,如果这是一个不起眼的问题,但我真的很感激解释。谢谢!

4 个答案:

答案 0 :(得分:6)

add()函数中,返回其局部变量result中保留的(直到函数退出)。函数返回后,变量的存储空间不再可用,但存储的值只是一个数字,而不依赖于该存储。

concat()函数中,表达式result指针计算为本地存储的10 char数组。您仍然可以返回指针的值,但是一旦该函数退出,该值的含义就不再被定义。

所以,不,返回值的行为在这些情况之间本身并不相同,但有用性 - 实际上与此相关的风险差别很大。

答案 1 :(得分:4)

  

行为会根据类型而有所不同吗?

有点儿。当您在C中返回某些内容时,将返回该值,而不是指向该值的指针或依赖于仍存在的任何变量的任何内容。但是,有一个不相关的规则表明,在几乎所有的上下文中,数组类型的值被隐式转换为指向数组的第一个元素的指针。因此,第二个代码片段将指针返回到数组中,而第一个片段只返回一个int。

答案 2 :(得分:1)

在第一个代码片段中,返回int变量的值。很好。

在第二个代码片段中,返回本地(堆栈)变量的地址。不行。


而且,也许是这句话:

char[10] result;

会更好:

char result[10];

如果第二个例子声明结果如下:

char result;

然后可以返回结果中的值:

return(result);

但是,第二个示例将结果定义为char数组;使结果成为指向此数组开头的指针。因此,第二个示例中结果的真值是本地堆栈内存的地址(当函数作用域终止时消失)。

第一个示例捕获结果的值(整数值)并将值发送回调用者,(不是函数本地范围中值的地址)。

答案 3 :(得分:0)

非常有趣的问题

当函数将局部变量作为vlue返回时,将创建一个新变量并将其存储在CPU寄存器中(取决于编译器)。之后,将释放局部变量。

 int add(int a, int b)
 {
     int result;
     result = a + b;

     return result; // 1. A new int variable will be created and stored in CPU registers (depends on Compiler)

     // 2. result will be freed at the end of function
 }

在CPP中,过程与C非常相似,卡构造函数将被调用两次

 struct Card card_create(enum Rank rank, enum Suit suit)
 {
     struct Card card;
     card.rank = rank;
     card.suit = suit;

     return card; // 1. New Card object will be created and stored in CPU register(Depends on compiler)

     // 2. card will be freed at the end of function
 }

希望得到这个帮助。