如何为我的自定义函数生成非空参数的警告?

raj*_*115 1 c gcc

我正在尝试编写一个库函数,其中参数不应为空,并且希望如果有人尝试传递 NULL,gcc 应该生成警告。我的代码是

\n\n
#include <stdio.h>\n#include <string.h>\nint own_strcmp(const char *str1, const char *str2)\n{\n        if( str1 == NULL || str2 == NULL){\n            if(str1 == NULL && str2 == NULL) \n                return 0;\n            else if( str1 == NULL)\n                return str2[0];\n            else\n                return str1[0];\n        }\n        int i=0;\n        while(str1[i] && str2[i]){\n                if( str1[i] != str2[i]){\n                        break;\n                }\n                i++;\n        }\n        return str1[i]-str2[i];\n}\n\n\n\nint main(int argc, char *argv[]){\n        const char *str1 = "hello";\n        const char *str2 = "hello";\n        printf("%s and %s is %d\\n", str1, str2, own_strcmp(NULL, str2));\n        printf("%s and %s is %d\\n", str1, str2, strcmp(NULL, str2));\n        return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于标准库的 strcmp,它用于生成警告。但对于我的功能来说却不是。

\n\n
rajesh@ideapad:~$ gcc own_strcmp.c\nown_strcmp.c: In function \xe2\x80\x98main\xe2\x80\x99:\nown_strcmp.c:21:2: warning: null argument where non-null required (argument 1) [-Wnonnull]\n  printf("%s and %s is %d\\n", str1, str2, strcmp(NULL, str2));\n  ^\n
Run Code Online (Sandbox Code Playgroud)\n

ex *_*ilo 5

也许声明GCCnonnull函数属性正是您所需要的。您可以指定所有指针参数都应为非空,也可以提供参数列表来指定哪些参数应为非空。

\n\n

我阅读文档的方式是,如果nonnull声明了该属性,则将空指针传递给非空参数是未定义的行为。必须启用该-Wnonnull选项才能收到警告。启用警告后,如果NULL传递给非空参数,则会发出警告。但是,对于传递的空指针变量,不会发出警告。因此,在运行时处理不正确的输入非常重要。感谢@alk指出这个重要问题。

\n\n

看起来Clang 也支持这个属性。Clang 还具有可为空类型限定符_Nonnull,但这在 GCC 中不可用。

\n\n

我应该强调的是,C 标准不支持这种行为,而是一种编译器扩展。为了可移植性,您应该使用设计良好的函数在运行时处理不正确的输入。

\n\n

NULL这是使用属性声明的函数(没有指针检查的早期版本)。我还添加了一行own_strcmp()使用空指针变量进行调用的行;请注意,此行不会导致发出警告。另请注意,调用标准库strcmp()无法触发警告。

\n\n
#include <stdio.h>\n#include <string.h>\n\nint own_strcmp(const char *str1, const char *str2)__attribute__((nonnull));\n\nint main(void)\n{\n    const char *str1 = "hello";\n    const char *str2 = "hello";\n    const char *arg = NULL;\n\n    /* Warning issued for this NULL argument */\n    printf("%s and %s is %d\\n", str1, str2, own_strcmp(NULL, str2));\n\n    /* No warning issued for the NULL variable arg */\n    printf("%s and %s is %d\\n", str1, str2, own_strcmp(arg, str2));\n\n    /* No warning issued for strcmp() either */\n    printf("%s and %s is %d\\n", str1, str2, strcmp(arg, str2));    \n    return 0;\n}\n\nint own_strcmp(const char *str1, const char *str2)\n{\n    int i=0;\n    while(str1[i] && str2[i]){\n        if( str1[i] != str2[i]){\n            break;\n        }\n        i++;\n    }\n    return str1[i]-str2[i];\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

以下是调用 GCC 后的输出:

\n\n
\xce\xbb> gcc -std=c11 -Wall -Wextra -Wpedantic warning_gcc_42035769.c\nwarning_gcc_42035769.c: In function \xe2\x80\x98main\xe2\x80\x99:\nwarning_gcc_42035769.c:13:5: warning: null argument where non-null required (argument 1) [-Wnonnull]\n     printf("%s and %s is %d\\n", str1, str2, own_strcmp(NULL, str2));\n     ^\n
Run Code Online (Sandbox Code Playgroud)\n

  • 作为OP的另一个注释:如果将变量传递给函数,则大多数情况下不会发出此警告。 (2认同)