我正在尝试编写一个库函数,其中参数不应为空,并且希望如果有人尝试传递 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}\nRun Code Online (Sandbox Code Playgroud)\n\n对于标准库的 strcmp,它用于生成警告。但对于我的功能来说却不是。
\n\nrajesh@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 ^\nRun Code Online (Sandbox Code Playgroud)\n
也许声明GCCnonnull函数属性正是您所需要的。您可以指定所有指针参数都应为非空,也可以提供参数列表来指定哪些参数应为非空。
我阅读文档的方式是,如果nonnull声明了该属性,则将空指针传递给非空参数是未定义的行为。必须启用该-Wnonnull选项才能收到警告。启用警告后,如果NULL传递给非空参数,则会发出警告。但是,对于传递的空指针变量,不会发出警告。因此,在运行时处理不正确的输入非常重要。感谢@alk指出这个重要问题。
看起来Clang 也支持这个属性。Clang 还具有可为空类型限定符_Nonnull,但这在 GCC 中不可用。
我应该强调的是,C 标准不支持这种行为,而是一种编译器扩展。为了可移植性,您应该使用设计良好的函数在运行时处理不正确的输入。
\n\nNULL这是使用属性声明的函数(没有指针检查的早期版本)。我还添加了一行own_strcmp()使用空指针变量进行调用的行;请注意,此行不会导致发出警告。另请注意,调用标准库strcmp()无法触发警告。
#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}\nRun 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 ^\nRun Code Online (Sandbox Code Playgroud)\n