【问题标题】:Why is taking address of function argument allowed in C?为什么在 C 中允许获取函数参数的地址?
【发布时间】:2021-10-26 02:53:48
【问题描述】:

假设我写了两个函数:

int f() {
    return 1;
}

int g() {
    int* x = &f();
}

我无法在 C 中编译它,因为您“无法获取右值的地址”。这是有道理的,因为来自f 的返回值存在于寄存器中。 (也就是说,它没有要分配的地址。)

另一方面,我可以编译这个:

int h(int x) {
    int* y = &x;
    return 0;
}

为什么? h 的参数也存在于寄存器中,因此它不应该有地址。我误会了什么?

【问题讨论】:

    标签: c function rvalue


    【解决方案1】:

    函数参数是具有自动存储期限的对象,就像函数内部的局部变量一样。

    C standard 的第 6.9.1p8 节对函数参数进行了如下说明:

    每个参数都有自动存储时长;它的标识符是一个左值。参数的存储布局未指定。

    而且因为函数参数是左值,所以可以取其地址。

    此外,虽然 C 标准没有明确规定,但函数参数通常像局部变量一样驻留在堆栈中。

    【讨论】:

    • 所以我有两个后续问题:1)我对 C 调用约定的理解是,所有参数都在寄存器中传递,直到用完,然后才将参数推入堆栈。 2)我认为指针只能具有堆上对象的地址,但不能指向堆栈中的内存区域。这两个都不对吗?
    • @broken.eggshell 调用约定是一个实现细节,一个指针可以指向任何个有效对象,无论它位于何处。 int x; int *y=&x没有问题。
    • @broken.eggshell 即使它们从寄存器开始,它们通常也不会停留在寄存器中。它们通常会溢出,然后您可以获取它们溢出的地址。
    • 为了澄清一件事...假设 int* y 是全局声明的,而不是在 h 内部,即 int* y; void h(int x) { y = &x; }h 返回后,y 又是一个悬空指针,对吗? x 是在堆栈上创建的,y 指出它的生命周期很短,但现在堆栈已展开,y 只是指向未使用的内存。
    • @RaymondChen:关于“他们通常会被泄露”:关于争论泄露频率的统计数据来自哪里?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    相关资源
    最近更新 更多