【发布时间】:2016-06-18 19:39:37
【问题描述】:
我正在使用一个不错的 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;
}
上面的例子是为测试目的而设计的(专门用来比较它编译的二进制代码)。
但是这非常有限,因为返回的数组的大小在函数的不同调用之间没有变化。
我怎样才能使返回的数组大小等于函数参数之一或此函数中的某个其他局部参数。
我不认为alloca 在这种情况下可以帮助我,因为它分配的内存会在函数退出 (IRC) 时立即销毁。
我想写这样的东西:
/*???*/ 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
}
换句话说,问号内的类型可能是什么?或者可能有其他解决方案(但不使用malloc)?
这种函数的理论用法理论上需要另一种类型来存储返回值,因为调用者无法获得返回结构的大小(除非有办法避免这种情况?)。但乍一看应该是这样的:
size_t size;
//scanf("%zu", &size);
struct {int _[size];} tmp; //create locally VM type
//compatible with the one
//returned by our theoretical func5
//we can't directly initialize tmp here (gcc complains)
tmp = ((__typeof__(tmp) (*)())func5)(); //direct assignment between VM structures
//works here on the other hand
//as function return value is rvalue and we can't
//take its pointer and cast it to our local VM structure type
//we instead cast the function pointer
如果我们这样做:
__typeof__(func5()) tmp = func5();
它不起作用,因为func5 的 VM 返回类型将取决于它的参数或局部变量。
然而,目前这只是理论上的,因为我们仍然无法定义这个函数。
【问题讨论】:
-
只要让调用者先分配数组,被调用者填入数值即可。
-
@user3528438 我对替代解决方案不感兴趣。我希望将 VLA 分配保留在被调用函数中(并且不使用
malloc)。 -
我想看看这是如何编码的。喜欢
{type_TBD func5(); type_TBD y = func5(); // use y }吗?你能发布一些使用func5()结果的理论代码吗? -
我想说的是,需要知道数组的大小之前
func5()被调用,以便y = func5()的y可以是声明。 -
您声称希望 VLA“被保存在被调用的函数中”,但您也想返回它。那必须制作副本,这意味着您需要在调用函数中使用 VLA 来接收副本。 (不管你怎么做,复制是必要的,因为你不能返回一个指向局部变量的指针。)所以唯一的解决方案是@user3528438 建议的那个,当然这也行不通,因为你需要有不同的不同大小的结构的函数版本。简而言之,使用malloc。这就是它的用途。
标签: c arrays gcc alloca gcc-extensions