数组下标的类型为’char’

我有以下代码从命令行读取参数。 如果字符串长度为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' 

问题是isdigit()宏接受一个参数,该参数是一个整数,它是值EOF或unsigned char的值。

ISO / IEC 9899:1999(C标准 – 旧),§7.4字符处理 ,¶1:

在所有情况下,参数都是一个int ,其值应表示为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 ... 

关于’函数退出的隐式定义’的警告意味着你没有包含但是你应该这样做。

你可能还会注意到,如果用户给你一个2作为第一个参数的第一个字符,退出状态将是50而不是2,因为'2'是(通常,在ASCII和UTF-8和8859-1中,等)字符代码50( '0'是48等)。 通过使用*args[1] - '0'作为exit()的参数,你得到2 (没有引号exit() 。 你不需要对该表达式进行强制转换,但它不会造成太大伤害。

您使用的编译器似乎有一个用于isdigit的宏(而不是函数,如果是这种情况,则不会发出警告)将该参数用作数组的下标。 这就是为什么isdigit将INT作为参数,而不是char。

删除警告的一种方法是将char转换为int:

 isdigit(*args[1]) => isdigit((int)(*args[1])) 

第二个警告意味着您要使用退出function,但尚未定义。 这意味着您必须执行所需的#include。

 #include  

是使用exit(int)函数的c库中的标准。

顺便说一句,如果此代码在您的“主”函数中,则不能检查“arg [1] == NULL”,如果用户未在命令行上提供任何参数,则可能导致分段错误。 您必须检查argc值(int参数)是否大于1。

你想要作为退出代码提供什么并不完全清楚,但是你可能想要args[1][0] - '0'代表字符所代表的十进制值,而不是字符的代码。

如果你这样做,你会产生副作用,即该表达式的类型是int ,你不会看到警告。

exit您可能忘记包含头文件。

尝试改变

 isdigit(*args[1]) 

 isdigit(args[1][0]) 

您的其他错误是因为您没有使用定义exit函数的#include