GCC:函数参数中的静态数组索引不会触发任何警告

GCC : Static array index in function argument doesn't trigger any warning

我正在尝试理解 "static" 关键字在 C 函数声明中用作数组索引的用法。

看完this article后,我试着声明了这样一个函数,并故意给它传递了一个太短的数组:

#include <stdio.h>
#include <stdlib.h>


void print_string10(char string10[static 10]) {

// Should trigger a warning if the argument is NULL or an array of less than 10 elements

    printf("%s\n",string10);

}

int main(void) {

    char short_string[] = "test";

    print_string10(short_string); // should trigger a warning as the string is 5 long

    return EXIT_SUCCESS;
}

使用文章中的 clang 进行编译会触发警告,但 gcc -Wall -Werror 不会,它编译并且 运行 正常。

我找不到解释,GCC 忽略此警告是正常行为吗?

看起来这是 GCC 中的错误。关于是否应该在编译时报告这一点,似乎存在一些分歧。尽管如此,它已被接受为一个错误,但似乎没有优先修复它。

这在错误报告 50584 中有详细说明。评论 9 特别指出:

(In reply to Malcolm Inglis from comment #4)

Could someone change the status of this bug?

无论功能是漂亮还是丑陋,GCC 都接受 如果可能,此代码和未定义行为的警告是 想要的。如此,确认。

这并不意味着任何人都会着手解决这个问题。请,如果 您正在使用此功能并希望在 GCC 中看到此警告, 请考虑贡献它: https://gcc.gnu.org/wiki/GettingStarted#Basics:_Contributing_to_GCC_in_10_easy_steps

如果你开始做这件事,最好在这里说一下。

为什么 不需要触发警告是因为它出现在标准的部分 - 6.7.6.3p7:

Semantics

[...]

  1. 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 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.

它出现在语义部分。仅需要一个符合规范的实现来诊断那些出现在 constraints 中的那些。即使它没有在这里诊断出违规,它也可以使用 static 关键字的知识来推断参数不为空,并且循环展开和其他优化可能期望一个数组至少有那么多元素。


另请注意,example 5 那里说

   void   f(double      (* restrict a)[5]);
   void   f(double      a[restrict][5]);
   void   f(double      a[restrict 3][5]);
   void   f(double      a[restrict static 3][5]);

都是兼容的,即您可以在函数指针赋值中混合和匹配它们而无需强制转换,即使它们具有 static 维度!

如果通过函数指针实现调用,clang 似乎(也许是正确的)失去了诊断任何东西的能力:

void (*f)(double a[restrict static 3]);

int main(void) {
    double a[1] = {0};
    f(a);
}

(在 Clang 7.0 中没有诊断 - 删除 * 你会得到它们)。