为什么没有出现“警告C4172局部变量返回地址或临时”错误?

为什么没有出现“警告C4172局部变量返回地址或临时”错误?,c,memory-management,C,Memory Management,此代码返回一个局部指针变量 但是,为什么不出现局部变量返回地址或临时错误的警告C4172 编译器不会输出任何错误 #include<stdio.h> static const char *test(void){ const char *a = NULL; char b[64] = {0,}; a = b; return a; } int main() { const char *a; a = test(); } 在C语言中,有两种错

此代码返回一个局部指针变量

但是,为什么不出现局部变量返回地址或临时错误的警告C4172

编译器不会输出任何错误

#include<stdio.h>

static const char *test(void){
    const char *a = NULL;
    char b[64] = {0,};
    a = b;
    return a;

}

int main() {
   const char *a;
   a = test();
}
在C语言中,有两种错误,我在这里非常松散地使用了错误这个术语。必须在编译时捕获的错误,编译器有义务发出诊断。在这种情况下,不能创建任何可执行文件

例如:

int foo() int
{
    return 24
}
上面的代码片段不是C程序,无法编译

另一种是运行时错误。虽然这里有几个,但我将重点讨论未定义的行为。其中某些部分上的某些程序具有语义,因此如果执行这些程序,则程序的行为是未定义的。这里值得注意的是,标准规定:无需诊断

让我们举一个与您相近的例子:

int* foo()
{
    int a;
    return &a;
}
这在技术上是合法的。使用指针是违法的。例如,如果您的程序在任何时候执行以下操作:

int* x = foo();
*x = 24;
那么您的程序有未定义的行为。编译器不需要发出任何诊断。这是因为在实践中,检查UB可能会变得非常困难、不可能或有很大的性能损失


另一方面,如果您的程序从未使用来自foo的指针,那么一切都正常。但是,由于返回的指针实际上是无用的,而且很可能是一个bug,所以大多数编译器都会尝试检测这种情况,并在编译时发出警告。恰好分析不够深入或复杂,无法检测特定情况下本地地址的返回。

显然编译器没有携带b是a本地的信息。指向的内存b点可以动态分配;如果在更改函数签名后返回&a,则肯定会收到警告。顺便说一句,gcc也没有抱怨。安全网只能延伸到目前为止……clang编译器似乎检测到了这个问题:`警告:与局部变量'b'关联的堆栈内存地址返回给调用者`@StoryTeller我希望优化器能够完全消除A。如果优化器可以看到这些东西,编译器也可以通过可接受的努力,至少有一个选项,这样我们就不会降低已知良好程序的编译时间。@PeterA.Schneider-另一方面,优化器可以将此程序减少到与返回0等价的程度;-因此,如果它再次出现,可能就没有什么可诊断的了。