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;
}
再次抱歉,如果这是一个愚蠢的问题,但我真的很希望你能解释一下。谢谢!

在您的add()函数中,您返回在其局部变量result中持有的(直到函数退出)。一旦函数返回,变量的存储空间就不再可用,但是存储在那里的值只是一个数字,本身并不依赖于该存储空间。

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

所以,不,在这些情况下返回值的行为本身并没有区别,但是与这样做相关的有用性——实际上是风险——差别很大。

不同类型的行为不同吗?

。当你在C语言中返回一些东西时,你返回的是值,而不是指向值的指针或任何依赖于仍然存在的变量的东西。然而,有一个不相关的规则说,在几乎所有上下文中,数组类型的值都被隐式地转换为指向数组第一个元素的指针。因此,第二个代码段返回一个指向数组的指针,而第一个代码段只返回一个int。

非常有趣的问题

当一个函数返回局部变量作为值时,一个新的变量将被创建并存储在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非常相似,card构造函数将被调用两次

 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
 }

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

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


也许还有这行:

char[10] result;

最好是:

char result[10];

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

char result;

则返回结果中的值:

return(result);

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

第一个示例捕获result的值(一个整数值)并将该值发送回调用者,而不是该值在函数局部作用域中的地址。

最新更新