use*_*165 3 c ctype compiler-warnings
我有以下代码从命令行读取参数.如果字符串长度为1个字符,并且我想将其用作退出值.编译器在第二行给出了警告(数组下标的类型为'char')此错误来自"&&"之后的第二部分.
if (args[1] != NULL) {
if ((strlen(args[1]) == 1) && isdigit(*args[1]))
exit(((int) args[1][0]));
else
exit(0);
}
}
Run Code Online (Sandbox Code Playgroud)
此外,当我使用不同的编译器时,我在下一行(退出)上得到两个错误.
builtin.c: In function 'builtin_command':
builtin.c:55: warning: implicit declaration of function 'exit'
builtin.c:55: warning: incompatible implicit declaration of built-in function 'exit'
Run Code Online (Sandbox Code Playgroud)
麻烦的是isdigit()宏接受一个参数,该参数是一个整数,它是值EOF或一个值unsigned char.
ISO/IEC 9899:1999(C标准 - 旧),§7.4字符处理<ctype.h>,1:
在所有情况下,参数都是a
int,其值应表示为unsigned char或等于宏EOF的值.如果参数具有任何其他值,则行为未定义.
在您的平台上,char已签名,因此如果您的字符在0x80..0xFF范围内,则将其视为负整数.isdigit()宏的通常实现是使用参数来索引标志位数组.因此,如果char从0x80..0xFF范围传递a ,则将在数组开始之前进行索引,从而导致未定义的行为.
#define isdigit(x) (_CharType[(x)+1]&_Digit)
Run Code Online (Sandbox Code Playgroud)
您可以安全地使用isdigit()以下两种方式之一:
int c = getchar();
if (isdigit(c))
...
Run Code Online (Sandbox Code Playgroud)
要么:
if (isdigit((unsigned char)*args[1]))
...
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,您知道该值不是EOF.请注意,这不行:
int c = *args[1];
if (isdigit(c)) // Undefined behaviour if *args[1] in range 0x80..0xFF
...
Run Code Online (Sandbox Code Playgroud)
关于"函数退出的隐式定义"的警告意味着你没有包含,<stdlib.h>但你应该这样做.
你可能还会注意到,如果用户给你一个2作为第一个参数的第一个字符,退出状态将是50而不是2,因为'2'(通常是ASCII和UTF-8和8859-1等)字符代码50('0'48等).2通过使用*args[1] - '0'作为参数,你得到(没有引号)exit().你不需要对该表达式进行强制转换,但它不会造成太大伤害.