2012-04-17 2 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.

ИСО/МЭК 9899: 1999 (C Стандарт – старые), §7.4 обработки <ctype.h>, ¶1 Характер:

Во всех случаях аргумент является int, значение которого должно быть представим в виде a unsigned char или должен быть равен значению макроса EOF.Если аргумент имеет любое другое значение, поведение не определено.

На вашей платформе, char подписан, так что если у вас есть символ в диапазоне 0x80..0xFF, он будет рассматриваться как отрицательное число. Обычная реализация макросов isdigit() заключается в использовании аргумента для индексации в массив бит флагов. Поэтому, если вы передадите char из диапазона 0x80..0xFF, вы будете индексировать до начала массива, что приведет к неопределенному поведению.

#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(). Вам не нужно прикладывать это выражение, хотя это не навредит.

+0

отлично, что позаботился о том, что «индекс массива имеет тип« char », но я все равно получаю неявное объявление о выходе. У меня уже есть #include в моем заголовке. – user994165

+0

Если 'exit()' не объявлен в '', то заголовок '', который используется, не работает. Уверены ли вы, что у вас нет пустого файла с именем '' где-то неожиданным? Используйте 'gcc -H', чтобы точно указать, какие заголовки включены. –

+0

Не знаете, что произошло, но теперь оно работает. благодаря – user994165

-1

Попробуйте изменить

isdigit(*args[1]) 

в

isdigit(args[1][0]) 

Ваши другие ошибки, потому что вы не используете #include <stdlib.>, который определяет функцию exit.

+2

Но если 'args [1]' является 'char *', не должен '* args [1]' быть 'char'? – Heinzi

+0

@cmh Я пробовал это и все еще получаю предупреждения. У меня был stdlib.h в заголовке. – user994165

+0

@ user994165 попробуйте использовать 'gcc -std = c99', как в [здесь] (http://stackoverflow.com/questions/1783792/why-does-gcc-report-implicit-declaration-of-function-round) – cmh

0

Это не совсем ясно, что вы хотите, чтобы дать как код завершения, но, вероятно, вы хотите args[1][0] - '0' для десятичного значения, что символ представляет и не код символа.

Если вы делаете это так, у вас будет побочный эффект, что тип этого выражения равен int, и вы не увидите предупреждения.

Для exit вы, вероятно, забыли включить заголовочный файл.

+0

I на самом деле я пытаюсь использовать фактический код символа, поэтому, если кто-то выводит exit 1 во вход, тогда я хочу дать команду exit (1) в моем коде. – user994165

+0

В этом случае вам нужно вычесть «0» (обратите внимание на кавычки!), Как предлагает Йенс, и, как я полагаю. –

1

Кажется, что у используемого вами компилятора есть макрос для isdigit (а не функция, у вас не было бы предупреждения, если бы это было так), который использует этот аргумент как индекс для массива. Вот почему isdigit принимает INT как аргумент, а не char.

Один из способов убрать предупреждение, что бросить свой символ в целое:

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

Второе предупреждение означает, что вы хотите использовать функцию выхода, но он еще не был определен. Это означает, что вы должны выполнить требуемый #include.

#include <stdlib.h> 

является стандартом в c-библиотеке для использования функции выхода (int).

BTW, если этот код находится в вашей «основной» функции, вы не должны проверять «arg [1] == NULL», что может привести к ошибке сегментации, если пользователь не предоставил никаких аргументов в отношении командная строка. Вы должны проверить, что значение ARGC (параметр INT) больше 1.

+3

Отбрасывание на 'int' удаляет предупреждение, но не представляет опасности; корректно указывать на 'unsigned char', а затем пусть это будет повышаться до' int'. –