允许在函数定义的返回类型中定义结构有什么关系?(C)

Pla*_*sky 3 c

最近我偶然发现了一些 C 代码,其中函数定义的返回类型本身就是一个结构体定义。例如,这个:

#include <stdio.h>

struct f {
    int a[25];       
    const char* ch;
} 
function(int h)
{
    printf("Passed: %d\n", h);
}

int main(int argc, char* argv[]) {
    printf("array at: %p ptr : %p\n", function(4).a, function(5).ch);
    int *ptr = function(6).a;
    for(int i = 0; i < 25; i++)
    {
      ptr[i] = i;
      printf("%d\n", ptr[i]);
    }
    puts("No segfaults.");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里自己测试。

我的问题是为什么会允许这样的事情?它实际上比定义struct正常有什么好处?你不能初始化变量,除非,我猜,你struct在函数内部创建一个,然后更改它的数据return。这是相当标准的票价,但问题是,clang 7.0.0您甚至不需要return任何东西!我认为void没有return语句的非函数是编译器错误(唯一的例外是main),但clang让您通过警告摆脱困境。

而且我们可以确定每个函数调用都会创建一个对象,因为我给出的代码没有段错误。尽管我不确定为什么它不是struct在堆栈上分配的,并且每当它超出范围(function结束时是正确的)时,它就会被释放并且地址将变为无效。在我的代码中,我可以写入我的程序不再拥有的位置,并且由于某种原因它没有段错误,但我不排除它是 UB 的可能性。

Aco*_*orn 5

我的问题是为什么会允许这样的事情?

C 语法中允许的很多东西可能不是特别好的风格。

在 clang 7.0.0 下你甚至不需要返回任何东西!我认为没有 return 语句的非 void 函数是一个编译器错误(唯一的例外是 main),但是 clang 通过警告让你摆脱困境。

只要调用者不使用该值(C 标准的 6.9.1p12),从具有非void返回类型的函数中流出而没有 a既不是错误也不是未定义的行为return

但这是非常糟糕的风格,因为调用者必须知道他们可以或不可以使用返回值的条件(加上返回值通常用于调用者需要检查的 C 中的错误代码)所以所有编译器实施警告。

除非,我猜,你在一个函数中创建一个结构,改变它的数据然后返回它。

嗯,这就是重点:您可以struct就地声明一个函数来返回多个值。

虽然我不确定为什么它不会因为结构被分配在堆栈上并且每当它超出范围(这是函数结束时正确)它会被释放并且地址将变得无效。

你是按价值返回的,这没有错。如果你说的是真的,即使返回一个int也会有问题。