2011-11-23 14 views
2

私がここで直面している主な問題は、strtoll()がVC 2010(error C3861: 'strtoll': identifier not found)でエラーとしてフラグが立てられていることです。 strtol()と交換すると同じことが起こりますか?次のCコードで何が問題になっていますか?

unsigned int get_uintval_from_arg(int argc, int index, char **argv, 
            unsigned int lower_bound, unsigned int upper_bound) 
{ 
    unsigned int return_val=0; 

    if (index + 1 <= argc - 1) 
    { 
     return_val=(unsigned int)strtoll(argv[index+1],NULL,10); 
     if (errno == EINVAL || errno== ERANGE) 
     { 
      fprintf(stderr, "Could not parse argument %s for switch %s!\n", 
        argv[index], argv[index+1]); 
      return 0; 
     } 
    } 
    // ....... I will post the remaining part of the code if necessary 
    ....... 
} 
+1

あなたのプログラムに##を含めましたか? 'long long'は' unsigned long'よりもずっと長いので、 'long long'バリアントを使用しようとしているのはなぜですか? – sarnold

+0

はい含まれています John

+2

'long long'は最新のISO 9899:99 C標準の一部であり、Microsoftがサポートしていない" C99 "です。 Visual Studioは、1990年から21年間のC標準のみをサポートしています。 – Lundin

答えて

5

あなたはおそらくC89以降の標準となっているので、(strtoll()一方のみC99以降の標準となっているとMSVCでサポートされていない)MSVCでサポートされてstrtoul()を使用する必要があり、unsigned intです。

エラー条件のテストでは適切ではありません。変換関数を呼び出す前にerrnoを0に設定する必要があります。エラーが報告されたかどうかを検出する必要があります。これは、見た目よりも面倒です。

セクション§7.20.1.4C99標準の 'strtolは、はstrtoll、strtoulを、およびstrtoull関数は、' 言う:

戻り

strtolstrtollstrtoul、およびstrtoull機能変換された 値を返します。変換が実行できない場合は、ゼロが返されます。正しい値 が表現可能な範囲の範囲外にある場合は、LONG_MIN、LONG_MAX、LLONG_MIN、 LLONG_MAX、ULONG_MAX、またはULLONG_MAXが返されます(戻り値の型 とその値があればそれに応じて)。マクロERANGEはerrnoに格納されます。

はまた、(変換された有効なゼロではなく)何の変換は行われなかったことを伝えるために変換関数にendptrパラメータに格納されている値を見て読む必要があります。

対象配列が空であるか、または予想される書式を持たない場合、 は変換されません。 nptrの値は、endptrが指すオブジェクトに格納されます。 の場合、endptrはNULLポインタではありません。これはテストよりも簡単であることを

unsigned int return_val=0; 

if (index + 1 <= argc - 1) 
{ 
    char *end; 
    unsigned long ul; 
    errno = 0; 
    ul = strtoul(argv[index+1], &end, 10); 
    if ((ul == 0 && end == argv[index+1]) || 
     (ul == ULONG_MAX && errno == ERANGE) || 
     (ul > UINT_MAX)) 
    { 
     fprintf(stderr, "Could not parse argument %s for switch %s!\n", 
       argv[index], argv[index+1]); 
     return 0; 
    } 
    retval = (unsigned int)ul; 
} 

注:(標準はEINVALにerrnoを設定し、これらの機能を言及していないので、EINVALに対するテストを省略)

だから、あなたはより多くのこのようなコードを記述する必要があります負の<type>_MINの制限と<type>_MAXの制限を考慮しなければならない符号付き整数変換の場合

実際に結果をunsigned longに記録し、指定された範囲内に収まるかどうかを確認する必要があります(UINT_MAXに制限されている可能性があります(UNIXのような64ビット環境ではULONG_MAX未満になる可能性があります) 。

+0

'errno = ERANGE' ?? :) – bdonlan

+0

また、64ビット長のプラットフォームの場合には、 'retval> UINT_MAX'も(unsigned intにダウンキャストする前に)チェックする必要があります。 – bdonlan

+0

@bdonlan:はい - ありがとう(両方のコメントに)。私はあなたのコメントを見ることなく、最後の段落でダウンキャストを修正しました(しかし、答えの初版にはそれが含まれておらず、あなたのコメントは上に掲載されています)。私は '=='の代わりに '='を忘れてしまっていました(しかし、コンパイラがコードをコンパイルしていると警告していました)。 –

1

In Visual Studioでは、代わりに_strtoi64()メソッドを使用します。それはstrtollと同じパラメータを持っています。あなたは、単に(あなたが移植を必要とする場合)など

#if defined(_MSC_VER) 
#define strtoll _strtoi64 
#endif 
+2

これは動作する可能性がありますが、移植性がありません。 –

+0

@PaulRうん、彼は特にVSを言った。彼はそれが移植可能にしたい場合は、Microsoft Cコンパイラでstrtollとして_strtoi64を再定義する定義を使用する必要があります。 –

+0

@bdonlanうん、私はその後、私は何かを無視してstrtollがうまくいかなかった理由を伝える前に、VS Cコンパイラにいくつかのコードを移植する問題があったので気づいた。 –

0

strtol()としてはstrtollとしてそれをラップする定義を使用することができます互換性のため

longのための適切なライブラリ関数です。移植性のために、return_valをlongまたはunsigned longとして宣言してください。後者の場合は、MSVCがstrtoul()を提供しているかどうかを確認してください。あなたの目的のために

+0

うーん、彼は長いロングintの散歩を使用していますが、unsigned intにキャストダウン...私はちょっとそのhehをスキップします。 –

+0

'long'と' int'が同じサイズの場合、これは 'INT_MAX + 1.UINT_MAX'の間の値を解析するための合理的な方法です。 – bdonlan

+0

@bdonlan: 'long'と' int'が同じサイズであると仮定すると近視眼的です。移植が簡単で簡単に書くことができます。環境に配慮した遅延ショートカットを使用しないようにしてください。重大な遅延は、最終的に破損するまでにかなりの時間を要します。 – wallyk

0

あなたがunsigned longタイプではなく、(strtollはどうなるのかである)signed long long型に変換しているとして、あなたは、strtoulを使用する必要があります。 long longで読み取る必要がある場合は、Microsoft固有の_strtoi64を使用してください。 #defineを使用して、Microsoftプラットフォームでstrtollに名前を変更するか、Windows固有の移植性shimsファイル(独自のプロトタイプをプライベートヘッダとして使用)にラッパー関数を記述することができます。あなたのreturn_val以来

関連する問題