如何让编译器检查数组长度?

How to make the compiler check an array length?

我定义了一个函数:

void myFunction(char string[20])
{
    // update my string here, maximal size is 20.
}

调用函数

char st[5];
myFunction(st);

是一个错误,因为 myFunction 破坏了导致未定义行为的堆栈。当然 st 的大小应该是 20(或更大)。

有没有办法让 c 编译器在发生此类错误时报错?推荐的此类调用编码方式是什么?

Of course st should be of size 20 (or greater).

您可以利用 C99 的静态数组索引功能,可用于 function declarators

If the keyword static 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 myFunction(char string[static 20])
{
    /* ... */
}

相反。如果传递的数组参数包含少于 20 个元素,这将触发编译器的警告。

例如,当使用 char [5] 类型的 st 调用 myFunction 时,clang 10 给我 warning: array argument is too small; contains 5 elements, callee requires at least 20 [-Warray-bounds]

然而,目前似乎只有 clang 支持 -Warray-bounds,GCC 正计划在 future.

中添加支持

请注意,这仅适用于数组的编译时,但它也会在传入 NULL 指针时发出警告(如果可以在编译时确定)。但是,有人可能会传递一个指向动态分配的元素少于 20 的数组的指针,而编译器无法在编译时对其进行静态检查。

所以对于这种情况,只有当参数的声明类型为 char [N] 时它才有效,其中 N 是它的大小,并且 N 至少为 20。如果你希望处理这两种情况,一个明确的大小参数将是必需的,并且在函数内部检查 return 如果传入的大小小于 20,则会出现错误。

你可以封装数组:

struct string20 { char string[20]; };
void myFunction(struct string20 *string)
{
}

或传递指向数组的指针(!=指向第一项的指针):

void myFunction( char (*string)[20] )
{
}
//....
char st[5];
char st20[20];
myFunction(&st); //WRONG; diagnosed error
myFunction(&st20); //OK

使用这两种方法中的任何一种,无论您的平台如何,您都将获得编译器诊断 (只要是符合标准的平台)。

您的函数如下所示:

void myFunction(char string[20])
{
    // update my string here, maximal size is 20.
}

但是,编译器是这样看的:

void myFunction(char *string)
{
    // update my string here, maximal size is 20.
}

大小“20”对编译器来说毫无意义。您可以使用任意长度的数组调用该函数。

关于通话:

char st[5];
myFunction(st);

完全没问题。

如果您想强制执行特定的数组大小,可以将数组包装在结构中。