Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在每个函数实例上返回大小不同的VLA?_C_Arrays_Gcc_Alloca_Gcc Extensions - Fatal编程技术网

C 如何在每个函数实例上返回大小不同的VLA?

C 如何在每个函数实例上返回大小不同的VLA?,c,arrays,gcc,alloca,gcc-extensions,C,Arrays,Gcc,Alloca,Gcc Extensions,我正在使用一个很好的GCC扩展,它允许我们在结构内部声明VLA。现在我找到了一种通过这种方式(通过值)将VLA传递给函数的方法。我也找到了一种返回一个的方法,但是在一个非常有限的上下文中 本例的功能代码如下: extern void func3() { size_t size; scanf("%zu", &size); struct tx{int _[size];} fn() { struct tx rt; for(s

我正在使用一个很好的GCC扩展,它允许我们在结构内部声明VLA。现在我找到了一种通过这种方式(通过值)将VLA传递给函数的方法。我也找到了一种返回一个的方法,但是在一个非常有限的上下文中

本例的功能代码如下:

extern void func3()
{
    size_t size;

    scanf("%zu", &size);

    struct tx{int _[size];} fn()
    {
        struct tx rt;

        for(size_t i=0; i < size; ++i)
            scanf("%d", &rt._[i]);

        return rt;
    }

    volatile __typeof__(fn) *pf = fn;
}
换句话说,问号内的类型是什么?或者可能还有其他解决方案(但不使用
malloc
)?

这种函数的理论用法在理论上需要另一种类型来存储返回值,因为返回结构的大小对调用方不可用(除非有办法避免这种情况)。但乍一看应该是这样的:

/*???*/ func5()
{
    size_t size;

    scanf("%zu", &size);

    struct {int _[size];} rt;

    for(size_t i=0; i < size; ++i)
        scanf("%d", &rt._[i]);

    return rt; //ok - return the structure
}
如果我们这样做:

/*???*/ func5()
{
    size_t size;

    scanf("%zu", &size);

    struct {int _[size];} rt;

    for(size_t i=0; i < size; ++i)
        scanf("%d", &rt._[i]);

    return rt; //ok - return the structure
}
它不起作用,因为
func5
的VM返回类型将取决于它的参数或局部变量。 然而,目前这些都是理论上的,因为我们仍然不能定义这个函数

[…]我希望VLA分配保存在被调用函数中(并且不使用
malloc

在C程序中,动态内存存储只有两个来源:堆和堆栈

您不想使用第一个,但第二个是自动管理的:当某个函数返回时,您在该函数“内部”分配的任何内容都将“消失”

当然,唯一的例外是返回值。不过,这并没有多大帮助,因为为了留在堆栈上,它的内存(如果通过堆栈返回)被“分配到”函数调用的参数之下。因此,在调用函数之前必须知道它的大小(否则就不知道在哪里存储函数的参数、局部变量等等)

由于“堆栈上的分配”本质上与“以已知字节数推进某个指针”相同,因此这里存在一个矛盾:您希望在函数内部进行分配,但在进入函数之前需要知道分配的数量

这行不通。

如何在每个函数实例上返回大小不同的VLA

返回VLA是一回事,除非通过,否则无法真正执行。(那么退回它的意义是什么)。除非事先确定了调用代码的大小,否则调用代码无法接收它


也许这已经足够接近OP的目标了

使用在已知大小后但在调用
func5()
之前分配的VLA

typedef struct {
  size_t size;
  int *a;
} va;

void func5(va *p) {
  for (size_t i = 0; i < p->size; ++i) {
    // error handling not shown
    // scanf("%d", &p.a[i]);
    p->a[i] = i;
  }
}

int main(void) {

  // create
  size_t size = 5;
  // scanf("%zu", &size);
  int v[size];
  va t = { size, v };

  // populate
  func5(&t);

  // use 
  for (size_t i = 0; i < size; i++) {
    printf("%d\n", t.a[i]);
  }

  // automatic "free"
  return 0;
}

到目前为止,我得到的最接近的方法是利用调用约定(在GCC下工作)-因此我们有一个生成器函数,它将生成数组大小-前半部分和后半部分填充返回的数组:

returnVLAgenerator(vlaout)
    char vlaout[];
{
    size_t szvla = 3; //calculate vlaout size here

    if(vlaout == 0)
        return szvla;

    while(szvla--) vlaout[szvla] = 'x'; //fill vlaout here

    return;
}
然后,如果您希望调用它,您需要生成一个带有函数签名和返回值的戳记,如下所示(示例main函数):

(main())
{
结构{char ar[returnVLAgenerator(0)]}(*returnVLAstamp)()=returnVLAgenerator,vlaOut;
vlaOut=returnVLAstamp();
对于(size_t i=0;i

这里有一些实时的

只需让调用方首先分配数组,被调用方只需填写值即可。@user3528438我对其他解决方案不感兴趣。我希望VLA分配保存在被调用的函数中(并且不使用
malloc
)。我试图了解这是如何编码的。像
{type_TBD func5();type_TBD y=func5();//使用y}
?你能发布一些使用
func5()
结果的理论代码吗?我想说的是,在调用
func5()
之前需要知道数组的大小,这样才能声明
y=func5()
y
。你声称希望VLA“保存在被调用的函数中”,但你也要退。这必须创建一个副本,这意味着您需要调用函数中的VLA来接收副本。(无论如何,复制是必要的,因为您无法返回指向局部变量的指针。)因此,唯一的解决方案是@user3528438建议的解决方案,当然,这也不起作用,因为对于不同大小的结构,您需要有不同版本的函数。简而言之,使用malloc。这就是它的用途。如果我能从参数中得到尺寸(与传递VLA的方式相同),也许会。但是,目前这在语法上是不可能的,因为在指定函数返回类型时函数参数不可见。但是也许还有其他的方法谁知道呢。这是正确的方法,尽管你可能应该去掉这个结构,只传递指针和大小。
0
1
2
3
4
returnVLAgenerator(vlaout)
    char vlaout[];
{
    size_t szvla = 3; //calculate vlaout size here

    if(vlaout == 0)
        return szvla;

    while(szvla--) vlaout[szvla] = 'x'; //fill vlaout here

    return;
}
(main())
{
    struct { char ar[returnVLAgenerator(0)]}(*returnVLAstamp)() = returnVLAgenerator, vlaOut;

    vlaOut = returnVLAstamp();

    for(size_t i = 0; i < sizeof(vlaOut.ar); ++i)
        printf("%c", vlaOut.ar[i]);

}