在阅读Modern C时,我试图检查如果我将空指针传递给以下任一函数,GCC 是否会引发诊断消息:
#include <stdio.h>
#include <stdlib.h>
#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_LLVM_COMPILER)
#define ATTRIB_NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
#else
#define ATTRIB_NONNULL(...) /* If only. */
#endif
size_t my_strlen(const char *s[static 1])
{
size_t count = 0;
while (*s++) {
++count;
}
return count;
}
ATTRIB_NONNULL(1) size_t my_strlen1(const char *s)
{
size_t count = 0;
while (*s++) {
++count;
}
return count;
}
int main(void)
{
return my_strlen(NULL), my_strlen1(NULL);
}
它产生的输出是这样的(
make null_diagnostic
):
null_diagnostic.c: In function ‘main’:
null_diagnostic.c:34:29: warning: argument 1 null where non-null expected [-Wnonnull]
34 | return my_strlen(NULL), my_strlen1(NULL);
| ^~~~~~~~~~
null_diagnostic.c:21:26: note: in a call to function ‘my_strlen1’ declared ‘nonnull’
21 | ATTRIB_NONNULL(1) size_t my_strlen1(const char *s)
| ^~~~~~~~~~
null_diagnostic.c:34:12: warning: argument 1 to ‘const char *[static 8]’ is null where non-null expected [-Wnonnull]
34 | return my_strlen(NULL), my_strlen1(NULL);
| ^~~~~~~~~~~~~~~
null_diagnostic.c:10:8: note: in a call to function ‘my_strlen’
10 | size_t my_strlen(const char *s[static 1])
| ^~~~~~~~~
它确实按预期提出了诊断信息,但它谈到将空指针传递给需要
const char *[static 8]
而不是 const char *[static 1]
的函数。为什么它期望参数的长度至少为 8?我错过了什么?
这是编译器信息:
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
这似乎是此版本的 gcc 中的一个错误,其中静态数组参数的大小乘以元素类型的大小,然后报告为静态大小。
看起来这是在 gcc 11.0 中引入的,并在 gcc 12.3 中修复了。