Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

c - array subscript has type 'char'

I have the following code to read an argument from the command line. If the string is 1 character long and a digit I want to use that as the exit value. The compiler gives me a warning on the second line (array subscript has type 'char' ) This error comes from the second part after the "&&" .

    if (args[1] != NULL) {
        if ((strlen(args[1]) == 1) && isdigit(*args[1]))
            exit(((int) args[1][0]));
        else
            exit(0);
    }
}

Also, when I use a different compiler I get two errors on the next line (exit).

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'
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The trouble is that the isdigit() macro takes an argument which is an integer that is either the value EOF or the value of an unsigned char.

ISO/IEC 9899:1999 (C Standard – old), §7.4 Character handling <ctype.h>, ?1:

In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

On your platform, char is signed, so if you have a character in the range 0x80..0xFF, it will be treated as a negative integer. The usual implementation of the isdigit() macros is to use the argument to index into an array of flag bits. Therefore, if you pass a char from the range 0x80..0xFF, you will be indexing before the start of the array, leading to undefined behaviour.

#define isdigit(x)  (_CharType[(x)+1]&_Digit)

You can safely use isdigit() in either of two ways:

int c = getchar();

if (isdigit(c))
    ...

or:

if (isdigit((unsigned char)*args[1]))
    ...

In the latter case, you know that the value won't be EOF. Note that this is not OK:

int c = *args[1];

if (isdigit(c))  // Undefined behaviour if *args[1] in range 0x80..0xFF
    ...

The warning about 'implicit definition of function exit' means you did not include <stdlib.h> but you should have done so.

You might also notice that if the user gives you a 2 as the first character of the first argument, the exit status will be 50, not 2, because '2' is (normally, in ASCII and UTF-8 and 8859-1, etc) character code 50 ('0' is 48, etc). You'd get 2 (no quotes) by using *args[1] - '0' as the argument to exit(). You don't need a cast on that expression, though it won't do much harm.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...