简体   繁体   English

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

[英]What's the deal with being allowed to define a struct in the return type of a function definition? (C)

Recently I stumbled upon some C code where the return type of a function definition was in itself a struct definition.最近我偶然发现了一些 C 代码,其中函数定义的返回类型本身就是一个结构体定义。 For example, this:例如,这个:

#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;
}

You can test this yourself here .你可以在这里自己测试。

My question is why would something like this be allowed?我的问题是为什么会允许这样的事情? What benefits does it actually have over defining a struct normally?它实际上比通常定义struct有什么好处? You can't init the variables, unless, I guess, you create a struct inside a function, change its data and then return it.你不能初始化变量,除非,我猜,你在struct内部创建一个struct ,改变它的数据然后return它。 Which is pretty standard-fare, but the thing is, under clang 7.0.0 you don't even need to return anything!这是非常标准的票价,但问题是,在clang 7.0.0您甚至不需要return任何东西! I thought non void functions having no return statements was a compiler error (with the only exception being main ), but clang lets you off the hook with a warning.我认为没有return语句的非void函数是一个编译器错误(唯一的例外是main ),但是clang通过警告让你摆脱clang

And also we can be sure that each function call results in an object created, as the code I gave doesn't segfault.而且我们可以确定每个函数调用都会创建一个对象,因为我给出的代码没有段错误。 Although I'm not sure why it doesn't as the struct is being allocated on the stack and whenever it would go out of scope (which is right when function ends) it would get deallocated and the address would become invalid.虽然我不确定为什么它不会因为struct被分配在堆栈上并且每当它超出范围(这是function结束时正确)它会被释放并且地址将变得无效。 In my code I can write to a location which my program no longer owns and for some reason it doesn't segfault, but I don't exclude the possibility of it being UB.在我的代码中,我可以写入我的程序不再拥有的位置,并且由于某种原因它没有段错误,但我不排除它是 UB 的可能性。

My question is why would something like this be allowed?我的问题是为什么会允许这样的事情?

There are many things allowed in the C grammar that may not be particularly good style. C 语法中允许的很多东西可能不是特别好的风格。

under clang 7.0.0 you don't even need to return anything!在 clang 7.0.0 下你甚至不需要返回任何东西! I thought non void functions having no return statements was a compiler error (with the only exception being main), but clang lets you off the hook with a warning.我认为没有 return 语句的非 void 函数是一个编译器错误(唯一的例外是 main),但是 clang 警告你让你摆脱困境。

It is not an error nor undefined behavior to flow out of a function with non- void return type without a return as long as the caller does not use the value (6.9.1p12 of the C standard).只要调用者不使用该值(C 标准的 6.9.1p12),从具有非void返回类型的函数中流出而不return就不是错误或未定义的行为。

But it is very bad style to do because then callers have to be aware of the conditions where they can or not use the return value (plus the return value is commonly used for error codes in C which the caller needs to check anyway) so all compilers implement a warning.但这是非常糟糕的风格,因为调用者必须知道他们可以或不可以使用返回值的条件(加上返回值通常用于调用者需要检查的 C 中的错误代码)所以所有编译器实施警告。

unless, I guess, you create a struct inside a function, change its data and then return it.除非,我猜,你在一个函数中创建一个结构,改变它的数据然后返回它。

Well, that is the point: you can declare a struct in-place to return several values from a function.嗯,这就是重点:您可以就地声明一个struct以从函数返回多个值。

Although I'm not sure why it doesn't as the struct is being allocated on the stack and whenever it would go out of scope (which is right when function ends) it would get deallocated and the address would become invalid.虽然我不确定为什么它不会因为结构被分配在堆栈上并且每当它超出范围(这是函数结束时正确)它会被释放并且地址将变得无效。

You are returning by value, there is nothing wrong with that.你是按价值返回的,这没有错。 If what you say were true, even returning an int would be a problem.如果你说的是真的,即使返回一个int也是一个问题。

Because it's syntatically and semantically valid and prohibiting it would increase complexity in the compiler.因为它在语法和语义上都是有效的,禁止它会增加编译器的复杂性。 It makes no sense to prohibit something that the benefits of leaving could exceed the costs of keeping.禁止离开的好处可能超过保留成本的东西是没有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM