我有以下代码来读取命令行参数。 如果字符串为1个字符长和一个数字我想用其作为退出值。 编译器给我在第二行上的警告(数组下标已键入“焦炭”)中的“&&”之后该错误来自于第二部分。
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'
麻烦的是,该isdigit()
宏接受一个参数,它是一个整数,或者是值EOF或的值unsigned char
。
ISO / IEC 9899:1999(C标准-旧),§7.4字符处理<ctype.h>
,¶1:
在所有情况下的参数为int
,其值应是可表示为unsigned char
或应等于宏EOF的值。 如果参数为其他值,则行为是不确定的。
在你的平台上, char
签订,所以如果你有在0x80..0xFF范围内的角色,它将被作为一个负整数处理。 通常执行的isdigit()
宏是使用参数来索引到标志位的阵列。 因此,如果你传递一个char
从0x80..0xFF的范围内,你将数组开始之前索引,导致不确定的行为。
#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()
你并不需要了解它的表达铸造,但它不会做多大的危害。
看来你使用编译器提供了ISDIGIT(而不是一个功能,你不会有一个警告,如果是这种情况),使用参数作为数组下标宏。 这就是为什么ISDIGIT接受一个int作为参数,而不是一个字符。
除去警告的一种方式,它投下您字符为int:
isdigit(*args[1]) => isdigit((int)(*args[1]))
第二个警告意味着你要使用的退出功能,但它尚未确定。 这意味着你必须做所需的#include。
#include <stdlib.h>
位于c-库中的标准使用退出(int)的函数。
顺便说一句,如果这个代码是在你的“主”的功能,你不能查“ARG [1] == NULL”,这可能导致分段故障,如果用户没有提供命令行任何参数。 你必须检查的argc值(INT参数)大于1。
这是不完全清楚你想要什么 ,得到退出代码,但可能你想args[1][0] - '0'
的十进制值的字符表示,而不是字符的代码。
如果你不喜欢它,你就会有副作用,就是该表达式的类型是int
,你不会看到警告。
对于exit
你可能忘了,包括头文件。
试着改变
isdigit(*args[1])
至
isdigit(args[1][0])
您的其他错误是因为你不使用#include <stdlib.>
定义了exit
功能。