C 调用约定是否阻止可变大小的返回值?

C 调用约定是否阻止可变大小的返回值?,c,calling-convention,variable-length-array,C,Calling Convention,Variable Length Array,如上所述,从C函数返回可变大小数据时,您可以: 传递一个指针和最大长度。返回指示是否达到最大值的标志 返回指向动态分配数据的指针 返回指向全局数据的指针 在典型硬件上调用约定是否会阻止通过调用堆栈返回动态大小的数据? 一些C编译器具有VLA(或alloca),因此调用堆栈上的可变大小数据是可能的。通过增加调用方的堆栈帧来实现可变大小的数组返回值似乎相当简单,就好像声明了VLA而不是函数调用一样。返回后,被调用方将离开元素计数,然后是元素。在VLAs之前,我们使用了alloca标准库函数,它实际上

如上所述,从C函数返回可变大小数据时,您可以:

  • 传递一个指针和最大长度。返回指示是否达到最大值的标志
  • 返回指向动态分配数据的指针
  • 返回指向全局数据的指针
  • 在典型硬件上调用约定是否会阻止通过调用堆栈返回动态大小的数据?


    一些C编译器具有VLA(或
    alloca
    ),因此调用堆栈上的可变大小数据是可能的。通过增加调用方的堆栈帧来实现可变大小的数组返回值似乎相当简单,就好像声明了VLA而不是函数调用一样。返回后,被调用方将离开元素计数,然后是元素。

    在VLAs之前,我们使用了
    alloca
    标准库函数,它实际上返回可变大小的数据。(碰巧数据未初始化,但这对实现不是必需的。)因此,显然这是可能的

    但是,有一个重要的细节:
    alloca
    在每次调用时分配存储,并且没有
    freea
    。释放存储的唯一方法是从调用alloca的函数返回

    对于本地存储分配来说,这是一个合理的接口,但对于返回有用数据的函数来说,这并不是一个很好的接口。如果在循环中调用
    functionWithVariableReturnSize()。这可能是不可取的,即使它与某些用例相匹配,也可能不是一个好主意。

    可变长度数组(这是可选功能)是C提供的唯一一种动态大小的数据结构,它具有不同于指针的源表示形式。然而,C甚至不提供任何机制来表示传递或返回的数组,因为数组值表达式会衰减为函数参数列表和
    return
    语句中的指针。然而,这不是一个调用约定的问题,而是语言设计中根深蒂固的方面


    当然,调用约定的考虑因素会影响函数返回值的实现,但是C实现在函数返回结构类型时,必须绕过那些最重要的考虑因素。如果C支持返回数组,那么我认为在调用约定方面不需要太多新的东西来支持返回VLA。

    如果返回了一个结构,那么结构的大小是已知的,因为它是在某处声明的。没有机制来判断堆栈上的动态大小数组有多少个元素。@Ctx我知道这一点。我们将尝试改进这个问题。您正在谈论的某种语言不是C语言。您所提出的语言有许多尖锐的优点,性能是迄今为止最大的问题。它有一个非常直接的解决方案,让调用者分配内存。对于锐利的优势,您需要一个协议来确保分配足够的资源。标准解决方案是调用函数两次。首先要确定需要的大小,同样要完成任务。您可以使用复合文本在调用者中分配堆栈变量:
    asctime_s((char[26]){0},26,localtime_r((time_t[1]){time(NULL)},&(struct tm){0})。返回动态大小的数据会阻止C标准,该标准规定VLA必须具有自动存储持续时间。@HansPassant为什么perf是最大的问题?
    alloca
    返回一个指向分配数据的指针,当然,这是OP列表中的#2(我将其视为)替代他询问的内容。@JohnBollinger我指的是分配给
    malloc
    @JohnBollinger的内存:alloca返回地址,但它将数据放在堆栈上。所以它不是真正的#2。你不能从函数返回数组,但是没有什么能阻止你返回
    struct{T[FIXED_SIZE];}
    。这仍然不允许您返回VLA,但我认为这表明,禁止返回阵列的禁令没有那么根深蒂固。确实如此,@rici。这就是我第二段的内容。