4

コマンドラインから引数を読み取る次のコードがあります。文字列の長さが 1 文字で数字の場合、それを終了値として使用したいと考えています。コンパイラは 2 行目に警告を表示します (array subscript has type 'char' )。このエラーは、"&&" の後の 2 番目の部分から発生します。

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

また、別のコンパイラを使用すると、次の行 (終了) で 2 つのエラーが発生します。

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:

すべての場合において、引数はでありint、その値はorとして表現可能であるunsigned charか、マクロEOFの値と等しくなければなりません。引数に他の値がある場合、動作は未定義です。

プラットフォームでは、charが署名されているため、0x80..0xFFの範囲の文字がある場合は、負の整数として扱われます。マクロの通常の実装はisdigit()、引数を使用してフラグビットの配列にインデックスを付けることです。したがって、char0x80..0xFFの範囲からaを渡すと、配列の開始前にインデックスが作成され、未定義の動作が発生します。

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

isdigit()次の2つの方法のいずれかで安全に使用できます。

int c = getchar();

if (isdigit(c))
    ...

また:

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

後者の場合、値がEOFにならないことがわかります。これはOKではないことに注意してください。

int c = *args[1];

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

'関数exitの暗黙的な定義'に関する警告は、含めなかったことを意味しますが、含める<stdlib.h>必要がありました。

また、ユーザーが最初の引数の最初の文字として2を指定した場合、終了ステータスは2ではなく50になります。これ'2'は、(通常、ASCII、UTF-8、8859-1などの)文字であるためです。コード50('0'48など)。の引数として2使用すると、(引用符なしで)取得できます。それほど害はありませんが、その表現にキャストする必要はありません。*args[1] - '0'exit()

于 2012-04-17T06:49:17.143 に答える
1

使用しているコンパイラには、配列の添字として引数を使用する isdigit (関数ではなく、その場合は警告が表示されない) のマクロがあるようです。そのため、isdigit は char ではなく INT を引数として取ります。

char を int にキャストするという警告を削除する 1 つの方法:

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

2 番目の警告は、exit 関数を使用したいが、まだ定義されていないことを意味します。つまり、必要な #include を実行する必要があります。

#include <stdlib.h> 

exit(int) 関数を使用するための c-library の標準です。

ところで、このコードが「メイン」関数にある場合、「arg[1] == NULL」をチェックしてはいけません。これにより、ユーザーがコマンドラインで引数を指定しなかった場合にセグメンテーション違反が発生する可能性があります。argc 値 (int パラメーター) が 1 より大きいことを確認する必要があります。

于 2012-04-17T06:46:32.073 に答える
0

終了コードとしてを指定するかは完全には明確ではありませんが、おそらくargs[1][0] - '0'、文字のコードではなく、文字が表す 10 進数値が必要です。

そのようにすると、その式の型が であるという副作用がありint、警告が表示されません。

ヘッダー ファイルをインクルードするのexitを忘れている可能性があります。

于 2012-04-17T06:36:18.327 に答える
-1

変更してみる

isdigit(*args[1])

isdigit(args[1][0])

あなたの他のエラーは、関数#include <stdlib.>を定義するものを使用していないためです。exit

于 2012-04-17T06:33:51.977 に答える