我试图了解在C函数声明中使用“ static”关键字作为数组索引的情况。
在阅读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忽略此警告的正常行为吗?
答案 0 :(得分:4)
这似乎是GCC中的错误。对于在编译时是否应报告此问题,似乎存在一些分歧。尽管如此,它还是被认为是一个错误,但是修复它似乎没有优先级。
错误报告50584中对此进行了详细说明。评论9特别指出:
(在评论4中回复Malcolm Inglis)
有人可以更改此错误的状态吗?
尽管功能是漂亮还是丑陋,GCC仍接受 可能的话,此代码和未定义行为的警告是 想要的。至此,证实。
这并不意味着任何人都将致力于解决此问题。请,如果 您正在使用此功能,并且希望在GCC中看到此警告, 请考虑贡献它: https://gcc.gnu.org/wiki/GettingStarted#Basics:_Contributing_to_GCC_in_10_easy_steps
如果您开始从事此工作,那么在这里这么说就很好。
答案 1 :(得分:4)
为什么为什么不需要触发警告是因为发生该标准的部分-6.7.6.3p7:
语义
[...]
- 将参数声明为“类型数组”调整为“类型的合格指针”,其中类型限定符(如果有)是在数组类型派生的[和]中指定的那些。如果关键字static也出现在数组类型派生的[和]中,则对于函数的每次调用,相应的实际参数应的值将提供对数组第一个元素的访问,至少与size表达式指定的元素数量相同。
它出现在语义部分中。只需要使用符合的实现来诊断出现在约束中的那些。即使未在此处诊断出违规情况,它也可以使用static
关键字的知识来推断参数不为null,并且展开循环和其他优化可能期望数组至少包含这么多数组元素。
还要注意,那里的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中没有诊断程序-删除*
,您将得到它们)。