array subscript has type 'char'

c, compiler-warnings, ctype

Solution

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.

Problem

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' ```

Original source

Related problems