4

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

4 回答 4

11

问题是isdigit()宏接受一个整数参数,它要么是 EOF 值,要么是unsigned char.

ISO/IEC 9899:1999(C 标准 - 旧),§7.4 字符处理<ctype.h>,¶1:

在所有情况下,参数都是 an int,其值应表示为 anunsigned char或应等于宏 EOF 的值。如果参数有任何其他值,则行为未定义。

在您的平台上,char是有符号的,因此如果您在 0x80..0xFF 范围内有一个字符,它将被视为负整数。宏的通常实现isdigit()是使用参数来索引标志位数组。因此,如果您char从 0x80..0xFF 范围内传递 a,您将在数组开始之前进行索引,从而导致未定义的行为。

#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(). 您不需要对该表达式进行强制转换,尽管它不会造成太大伤害。

于 2012-04-17T06:49:17.143 回答
1

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

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

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

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

#include <stdlib.h> 

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

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

于 2012-04-17T06:46:32.073 回答
0

目前尚不完全清楚您想要作为退出代码给出什么,但您可能想要字符args[1][0] - '0'表示的十进制值而不是字符的代码。

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

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

于 2012-04-17T06:36:18.327 回答
-1

尝试改变

isdigit(*args[1])

isdigit(args[1][0])

你的其他错误是因为你没有使用#include <stdlib.>which 定义了exit函数。

于 2012-04-17T06:33:51.977 回答