- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
CERT's Secure Coding Standard包括一项 ( API05-C ),它鼓励使用一致的数组参数,这是我在很多代码中实现的建议(对于不支持它们的编译器,隐藏在 a macro 后面)。
对于那些不知道的人,一致的数组参数是这样的:
void foo(int length, char data[length]);
API05-C提供更多信息。
许多编译器不喜欢可变长度数组(有充分的理由)。 C11 将它们从必需(就像在 C99 中一样)降级为可选(如果未实现,编译器应定义 __STDC_NO_VLA__
)。 MSVC 完全不支持它们。 IAR 将它们隐藏在一个开关后面 (--vla
)。如果您询问(使用 -Wvla
,或者如果您想要错误,则使用 -Werror=vla
),GCC 和 clang 会警告您。
一致的数组参数不会遇到与“普通”可变长度数组相同的问题;它们不会导致变量堆栈的使用。它们只是告诉编译器现有数组有多大(可能位于堆栈或堆上)。
我的问题是,我所知道的每个编译器都将一致的数组参数视为 VLA。对于像 MSVC 这样的编译器来说这不是什么大问题,因为我可以将我的宏定义为空,但是对于像 GCC 和 clang 这样的编译器我想使用一致的数组参数但不想触发 -Wvla
诊断。
根据 API05-C(添加了重点):
Consequently, an array declaration that serves as a function argument may have an index that is a variable or an expression. The array argument is demoted to a pointer and is consequently not a variable length array (VLA). Conformant array parameters can be used by developers to indicate the expected bounds of the array. This information may be used by compilers, or it may be ignored. However, such declarations are useful to developers because they serve to document relationships between array sizes and pointers. This information can also be used by static analysis tools to diagnose potential defects.
我非常希望这是真的,但我似乎找不到 C99 的相关部分或 C11标准。
那么,严格基于 C99/C11 标准,一致的数组参数是否为 VLA?或者,换句话说,将数组作为参数传递真的会将其降级为指针吗?
显然,请引用规范的相关部分。
最佳答案
所有声明为数组类型的参数都被转换为指针类型。 VLA 也不异常(exception)。
N1256(C99+TC1+TC2+TC3):
6.7.5.3 Function declarators (including prototypes)
7 A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the
[
and]
of the array type derivation. If the keywordstatic
also appears within the[
and]
of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
声明为 void f(int a[10]);
的函数采用任何 int *
。声明为 void f(int length, int array[length]);
的函数采用 int
和 int *
。
但是,你写:
My issue is that every compiler I'm aware of treats conformant array parameters as VLAs. This isn't such a big deal for compilers like MSVC since I can just define my macro to nothing, but for compilers like GCC and clang I want to use conformant array parameters but don't want to trigger
-Wvla
diagnostics.
嗯,这很棘手。在转换为指针之前,它是一个 VLA,-Wvla
的目的是警告在不支持 VLA 的编译器上无法编译的代码。如您所见,MSVC 不喜欢该代码。
Conformant array parameters don't suffer from the same problems as "normal" variable-length arrays; they don't result in variable stack usage. They just tell the compiler how big an existing array, which could be on the stack or heap, is.
不,他们不会那样做。给定 void f(int a[10]);
,使用空指针、指向长度为 1 的数组的指针等调用 f
是完全有效的。编译器必须支持它。它们仅作为对人类读者的提示。这同样适用于转换后的 VLA。
关于c - 一致的数组参数是 VLA 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49962479/
在this post ,OP 包含有很多错误的代码,但是 1 行让我特别好奇,因为我无法查找任何东西,不允许它。这是具体的行: int n = 100000, arr[n]; 是否保证了声明和初始化的
我需要定义一个结构体,其中包含两个信号量和三个(至少)或更多数组作为大小为变量的结构体成员。指示性示例(不是正确的语法,而是给出上下文含义;lr 是 double 的 typedef): int
函数的参数可以在后面的参数中使用吗?这是不好的形式吗? void print(int n, int m, int matrix[n][m]) { for (int i=0; i
C11 允许像这样使用 VLA 数组(和矩阵) int row = 10; int col = 10; double matrix[row][col]; 但是如果我只想将矩阵的一行传递给一个函数,我可
我写了最简单的矩阵乘法代码来完成我对 C99 VLA 的理解。让我有点困惑的是,当我在函数定义的参数列表中声明一个指向 VLA 的指针时。 例如,在 fill_matrix_randomly 中,声明
这样的函数原型(prototype)在 C 中有效吗? int (*func())[*]; 如果是,我该如何定义这样的函数? 最佳答案 您应该返回一个指向不完整数组类型的指针,因为可变长度数组的 *
在 C 中,我相信以下程序是有效的:将指向已分配内存缓冲区的指针转换为数组,如下所示: #include #include #define ARRSIZE 4 int *getPointer(in
您可能知道,VLA's haves pros and cons 和它们在 C11 中是可选的。 我想使 VLA 成为可选项的主要原因是:“堆栈可能会爆炸”: int arr[n]; /* where
我了解什么是可变长度数组以及它们是如何实现的。这个问题是关于它们为什么存在。 我们知道 VLA 只允许在功能块(或原型(prototype))中使用,并且它们基本上不能在堆栈上的任何地方(假设正常实现
这是允许的吗? goto inside; { inside: int a[n]; } A goto statement shall not jump from outside the scope of
我注意到 C 编译器(gcc、clang、tinycc)允许我在没有警告的情况下将指向较大数组的指针分配给指向较小 VLA 的指针: #include #if !__TINYC__ void tak
我使用以下结构来使用隐写术对带有消息的 PPM 文件进行编码: typedef struct{ char code[CODE_LENGTH]; COMMENT *commentPPM;
进一步开发昨天的代码( seg fault caused by malloc and sscanf in a function ),我尝试在网上找到的一些教程的帮助下生成一个 2-dim vla。但我
我有以下无法编译的代码。 using namespace std; void f(int); template void array_ini_1d(T1 (&x)[N]) { for (int i
我在 SO 上阅读了有关 VLA 的不同答案,但找不到答案。就我而言,我有一个分配内存的函数: template void allocMemory(T *&data, const size_t num
这是一种定义矩阵类型的方法 typedef struct { int nr, nc; double *elem; } Matrix; 我想定义这个 typedef struct {
我试图了解 sizeof 运算符的工作原理,我遇到了 this问题。以下是该问题的代码 #include int main() { int i = 0; int a[i];
CERT's Secure Coding Standard包括一项 ( API05-C ),它鼓励使用一致的数组参数,这是我在很多代码中实现的建议(对于不支持它们的编译器,隐藏在 a macro 后面
(这是后续 to this question 。) 我试图了解将多维数组传递给 C 中的函数的“最佳实践”(或任何实际实践)是什么。当然这取决于应用程序,所以让我们考虑编写一个函数来打印二维数组可变大
我们已经知道,VLA (在 C99 中标准化)不是 C++ 标准的一部分。 所以下面的代码在 C++ 中是“非法的”: void foo(int n) { int vla[n]; for (i
我是一名优秀的程序员,十分优秀!