将VLA的大小作为指针引用传递
你能把可变长度数组(VLA)的大小作为一个大型结构中的元素传递,并把它用作VLA的大小吗?
void foo(largeStructType* largeStructPtr, int arr[largeStructPtr->size])
然而有一个AI助手抱怨,在C99中,VLA的大小只能是常量或直接的函数参数,不能通过解引用获得。我对那条评论不太信任。这段代码可以工作,且gcc在 -std=c99下编译通过。请努力理解并阅读C 标准,但我仍无法就它是否有效给出结论。这个社区能不能带来一些指点,告诉它是否符合标准?
更新: 感谢你们的所有精彩评论!我的问题归结为下面这种情况是否符合标准?
void foo(largeStructType* largeStructPtr, int arr[largeStructPtr->size])
当所有示例都只有这样的形式时
void foo(int size, int arr[size])
解决方案
可以把可变长度数组(VLA)的大小作为大型结构中的一个元素传递,并把它用作VLA的大小吗?
当然可以传递这个大小。这个大小只是一个数值,你可以传递数值。
你可以使用这个大小。这个大小只是一个数值,你可以使用该数值。
然而,“把它用作VLA的大小”到底是什么意思?在哪段代码中你需要为VLA指定大小?
让我们看看你的声明:
void foo(largeStructType* largeStructPtr, int arr[largeStructPtr->size])
这条声明将 arr 声明为指向 int 的指针。它看起来像是把 arr 声明为一个数组,但它实际上声明的是 arr 为一个指向 int 的指针,因为C 2024标准的6.7.7.4条规定:
… 将参数声明为“array of type”应调整为“qualified pointer to type”,其中数组类型推导中的限定符(如有)由
[和]指定…
所以我们不在意这个函数声明看起来像是把 arr 声明为一个变长数组,因为最终它并没有声明一个数组,只是一个指向 int 的指针。你也可以用这两种写法中的任意一种来写声明,它们与原始版本等价:
void foo(largeStructType *largeStructPtr, int arr[]) …
void foo(largeStructType *largeStructPtr, int *arr) …
在函数内部,这个声明并不会产生变长数组。arr 是一个指针,你可以用它通过 arr[i] 访问原数组的元素。
如果在函数内部使用数组的大小来控制对数组的下标,使所有下标都在正确的边界内,那就没问题。你也可以在函数内部用这个大小来描述一个变长数组,而不仅仅是一个指针,但你可能不需要这么做。如果你确实觉得需要,请提出一个新问题,描述你的需求。
你也可以把函数写成参数是指向变长数组的指针的形式:
void foo(largeStructType *largeStructPtr, int (*arr)[largeStructPtr->size]) …
在这种情况下,arr 不会再被调整——它已经是一个指针,而不是数组,因此不存在把数组转换为指针的调整。它指向一个数组,但自动调整仅针对直接数组,而不适用于指向数组的指针。
然而,在代码中传递指向变长数组的指针并不常见,除非确实有特殊需要,否则不应使用它。