2012-04-17 34 views
1

我有以下代码从命令行读取参数。如果字符串是1个字符,并且我想用它作为出口值。编译器在第二行给出警告(数组下标具有类型'char')。此错误来自“& &”之后的第二部分。数组下标有'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' 

回答

6

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

ISO/IEC 9899:1999(C标准–旧),§7.4字符处理<ctype.h>,¶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 
    ... 

约“退出函数的定义隐含”的警告意味着你没有包括<stdlib.h>但你应该这样做。

您可能还会注意到,如果用户给出了2作为第一个参数的第一个字符,退出状态将是50而不是2,因为'2'(通常是ASCII和UTF-8和8859- 1等)字符码50('0'是48等)。通过使用*args[1] - '0'作为exit()的参数,您会得到2(不含引号)。你不需要在表达式上施放,尽管它​​不会造成太大伤害。

+0

伟大的,这照顾了“数组下标具有类型'char'”警告,但我仍然得到隐式声明退出。我的标题中已包含#include 。 – user994165 2012-04-17 07:03:18

+0

如果'exit()'没有在''中声明,那么正在使用的''标题被破坏。你确定你没有一个名为''的空文件出现在某个意想不到的地方吗?使用'gcc -H'来查看包含哪些标题。 – 2012-04-17 07:05:05

+0

不知道发生了什么,但现在正在工作。谢谢 – user994165 2012-04-17 07:40:01

-1

尝试改变

isdigit(*args[1]) 

isdigit(args[1][0]) 

您的其他错误是因为您没有使用#include <stdlib.>定义了exit功能。

+2

但是,如果'args [1]'是一个char *',那么''args [1]'不应该是'char'吗? – Heinzi 2012-04-17 06:37:39

+0

@cmh我试过了,仍然收到警告。我的头里有stdlib.h。 – user994165 2012-04-17 06:39:52

+0

@ user994165尝试在[here]中使用'gcc -std = c99'(http://stackoverflow.com/questions/1783792/why-does-gcc-report-implicit-declaration-of-function-round) – cmh 2012-04-17 06:43:17

0

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

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

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

+0

I实际上我试图使用字符的实际代码,所以如果有人在输入中键入exit 1,那么我想在我的代码中给出命令exit(1)。 – user994165 2012-04-17 06:41:15

+0

在这种情况下,你需要减去''0''(注意引号!),正如Jens所建议的那样,正如我所建议的那样。 – 2012-04-17 07:10:53

1

看来你使用的编译器有一个用于isdigit的宏(而不是一个函数,如果是这种情况,你不会有警告)使用参数作为数组的下标。 这就是为什么isdigit需要INT作为参数,而不是char。

一种方式来删除警告它来投你的字符为int:第二个警告意味着你要使用exit函数

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

,但尚未确定。这意味着您必须执行所需的#include。

​​

是c-library中使用exit(int)函数的标准。如果这个代码在你的“main”函数中,你不能检查“arg [1] == NULL”,如果用户没有提供任何参数,那么这可能导致分段错误。命令行。您必须检查argc值(int参数)是否大于1.

+3

投射到'int'会消除警告,但不会危险;将'unsigned char'强制转换为'int'是正确的。 – 2012-04-17 06:50:18

相关问题