首页 > 解决方案 > GCC:函数参数中的静态数组索引不会触发任何警告

问题描述

我试图了解在 C 中的函数声明中使用“静态”关键字作为数组索引。

读完这篇文章后,我尝试声明这样一个函数,并有目的地传递一个太短的数组:

#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;
}

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

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

标签: cgccclanggcc-warning

解决方案


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

语义

[...]

  1. 将参数声明为“类型数组”应调整为“类型限定指针”,其中类型限定符(如果有)是在数组类型派生的 [ 和 ] 中指定的那些。如果关键字 static 也出现在数组类型派生的 [ 和 ] 中,则对于函数的每次调用,对应的实际参数的值提供对至少与指定元素一样多的数组的第一个元素的访问由大小表达式。

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


还要注意,那里的示例 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 中没有诊断 - 删除*,你会得到它们)。


推荐阅读