C语言函数局部变量回收问题

C新手,请教下局部变量的回收问题。
今天写个链表,结果我发现下面 test_add 方法里声明的局部变量好像并没有被回收,用的是同一个内存地址的空间,所以,第二次调用函数,重新声明的变量依然用的是上一次的赋值。
我想问下这是什么原因?按照我自己理解局部变量应该会用新地址,但实际不是,是因为C标准这么规定的吗?

#include <stdio.h>

void test_add(int n);

typedef struct node_s node_t;

struct node_s {
    int num;
    node_t *next;
};

static node_t node_queue;

int main(int argc, char *argv[]) {
    node_queue.next = &node_queue;
    test_add(1);
    test_add(2);
    test_add(3);
    for (node_t *temp = node_queue.next; temp != &node_queue; temp = temp->next) {
        printf("%dn", temp->num);
    }
    return 0;
}

void test_add(int n) {
    node_t new_node;
    // 本来以为重新调用方法,new_node 应该是新分配的空间才对,但其实用的旧的
    printf("声明:%d\n", new_node.num);
    printf("地址:%p\n", &new_node);
    new_node.num = n;
    // 插入队列, 因为 new_node 的地址没变,导致 queue 里的队列不正确
    new_node.next = node_queue.next;
    node_queue.next = &new_node;
}

test_add 里的输出结果:
声明:-335181312
地址:0x7ffeec0589a8
声明:1
地址:0x7ffeec0589a8
声明:2
地址:0x7ffeec0589a8

gcc 环境是:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

阅读 3.1k
1 个回答

局部变量的地址是在堆栈上,其实并没有没有回不回收的概念,你三次test_add都是在同一层堆栈调用的,自然地址都是一样的
你要是像评论里说的那样递归去调用(或者其他方法),让test_add在不在同一层堆栈,申请到的地址就不一样了
想要多了解原理可以学学汇编相关的知识
而且我看了看你的需求,你add一个新节点不应该使用局部变量(局部函数退出后,这块内存随时可能会被别处使用,就会出问题),而是应该手动申请一块新内存去给新节点使用

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进