我有以下代码从命令行读取参数。如果字符串长度为1个字符,并且我想将其用作退出值。编译器在第二行给出了警告(数组下标的类型为'char')此错误来自“&&”之后的第二部分
if (args[1] != NULL) {
if ((strlen(args[1]) == 1) && isdigit(*args[1]))
exit(((int) args[1][0]));
else
exit(0);
}
}
另外,当我使用不同的编译器时,我在下一行(退出)上遇到两个错误。
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'
答案 0 :(得分:8)
麻烦的是isdigit()
宏接受一个参数,该参数是值EOF或unsigned char
的值。
ISO / IEC 9899:1999(C标准 - 旧),§7.4字符处理<ctype.h>
,¶1:
在所有情况下,参数都是
int
,其值应为。{1}} 可表示为unsigned char
或等于宏EOF的值。如果 参数有任何其他值,行为未定义。
在您的平台上,char
已签名,因此如果您的字符在0x80..0xFF范围内,则会将其视为负整数。 isdigit()
宏的通常实现是使用参数索引到标志位数组。因此,如果从0x80..0xFF范围内传递char
,则将在数组开始之前进行索引,从而导致未定义的行为。
#define isdigit(x) (_CharType[(x)+1]&_Digit)
您可以通过以下两种方式之一安全地使用isdigit()
:
int c = getchar();
if (isdigit(c))
...
或:
if (isdigit((unsigned char)*args[1]))
...
在后一种情况下,您知道该值不是EOF。请注意,这不行:
int c = *args[1];
if (isdigit(c)) // Undefined behaviour if *args[1] in range 0x80..0xFF
...
关于“函数退出的隐式定义”的警告意味着您没有包含<stdlib.h>
,但您应该这样做。
你可能还会注意到,如果用户给你一个2作为第一个参数的第一个字符,退出状态将是50而不是2,因为'2'
是(通常是ASCII和UTF-8)和8859-1等)字符代码50('0'
是48等)。使用2
作为*args[1] - '0'
的参数,您将获得exit()
(无引号)。你不需要对该表达式进行强制转换,但它不会造成太大伤害。
答案 1 :(得分:1)
您使用的编译器似乎有一个用于isdigit的宏(而不是一个函数,如果是这样的话就不会有警告),它使用该参数作为数组的下标。 这就是为什么isdigit将INT作为参数而不是char。
删除警告它将char转换为int的一种方法:
isdigit(*args[1]) => isdigit((int)(*args[1]))
第二个警告意味着您要使用退出功能,但尚未定义。这意味着您必须执行所需的#include。
#include <stdlib.h>
是c-library中使用exit(int)函数的标准。
BTW,如果此代码在“main”函数中,则不能检查“arg [1] == NULL”,如果用户未在命令上提供任何参数,则可能导致分段错误-线。您必须检查argc值(int参数)是否大于1.
答案 2 :(得分:0)
你想要作为退出代码提供什么并不完全清楚,但是你可能希望args[1][0] - '0'
代表字符所代表的十进制值,而不是字符代码。< / p>
如果您这样做,您会产生副作用,即该表达式的类型为int
,您将看不到警告。
对于exit
,您可能忘记包含头文件。
答案 3 :(得分:-1)
尝试更改
isdigit(*args[1])
到
isdigit(args[1][0])
您的其他错误是因为您没有使用定义#include <stdlib.>
功能的exit
。