2013-08-19 5 views
5

私は整数型ファミリー(charunsigned charshortunsigned shortint、...)の値が任意の準拠のCコンパイラでコンパイルすることができますマクロで可能ならばCの負の数であるかどうかを検出しようとしています(したがって、gccは許可されていません)警告なしマクロでの符号量の検出方法は?

私は次のように付属のいくつかの時間後:

#define ISNEG(X) ((X) && (X-1) && ((X <= 0) && (~X >= 0))) 

私は、次の例でそれを試してみました:

void 
display_result(int arg, int result) 
{ 
    printf("ISNEG(%d) is %stive\n", arg, (result ? "nega" : "posi")); 
} 

void 
display_uresult(unsigned int arg, int result) 
{ 
    printf("ISNEG(%u) is %stive\n", arg, (result ? "nega" : "posi")); 
} 

int main() 
{ 
    short shrt = 5; 
    short nshrt = -5; 
    unsigned short ushrt = 5; 

    display_result(shrt, ISNEG(shrt)); 
    display_result(nshrt, ISNEG(nshrt)); 
    display_uresult(ushrt, ISNEG(ushrt)); 

    int ni = -5; 
    int i = 5; 
    int zero = 0; 

    display_result(ni, ISNEG(ni)); 
    display_result(i, ISNEG(i)); 
    display_result(zero, ISNEG(zero)); 
    display_result(~zero, ISNEG(~zero)); // wrong 

    unsigned int uzero = 0; 
    unsigned int ui = 5; 

    display_uresult(uzero, ISNEG(uzero)); 
    display_uresult(~uzero, ISNEG(~uzero)); 
    display_uresult(ui, ISNEG(ui)); 

    long int li = -5; 
    unsigned long int uli = 5; 

    display_result(li, ISNEG(li)); 
    display_uresult(uli, ISNEG(uli)); 

    long long int lli = -5; 
    unsigned long long int ulli = 5; 

    display_result(lli, ISNEG(lli)); 
    display_uresult(ulli, ISNEG(ulli)); 

    return EXIT_SUCCESS; 
} 

そして、結果は次のとおりです。

ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 
ISNEG(0) is positive 
ISNEG(-1) is negative 
ISNEG(0) is positive 
ISNEG(4294967295) is positive 
ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 

それは動作しますかなり良いですが、問題は、すべての警告(-Wall -Wextra)でコンパイルすると、次のようになりますINGのメッセージ:

signedness.c: In function ‘main’: 
signedness.c:27:3: warning: promoted ~unsigned is always non-zero [-Wsign-compare] 
    display_uresult(ushrt, ISNEG(ushrt)); 
^
signedness.c:4:49: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] 
#define ISNEG(X) ((X) && (X-1) && ((X <= 0) && (~X >= 0))) 
               ^
signedness.c:41:26: note: in expansion of macro ‘ISNEG’ 
    display_uresult(uzero, ISNEG(uzero)); 
         ^
signedness.c:4:49: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] 
#define ISNEG(X) ((X) && (X-1) && ((X <= 0) && (~X >= 0))) 
               ^
signedness.c:42:27: note: in expansion of macro ‘ISNEG’ 
    display_uresult(~uzero, ISNEG(~uzero)); 
         ^
signedness.c:4:49: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] 
#define ISNEG(X) ((X) && (X-1) && ((X <= 0) && (~X >= 0))) 
               ^
signedness.c:43:23: note: in expansion of macro ‘ISNEG’ 
    display_uresult(ui, ISNEG(ui)); 
        ^
signedness.c:4:49: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] 
#define ISNEG(X) ((X) && (X-1) && ((X <= 0) && (~X >= 0))) 
               ^
signedness.c:49:24: note: in expansion of macro ‘ISNEG’ 
    display_uresult(uli, ISNEG(uli)); 
         ^
signedness.c:4:49: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] 
#define ISNEG(X) ((X) && (X-1) && ((X <= 0) && (~X >= 0))) 
              ^
signedness.c:55:25: note: in expansion of macro ‘ISNEG’ 
    display_uresult(ulli, ISNEG(ulli)); 
         ^

だから、私の質問は以下のとおりです。

  1. 我々はC言語のすべての可能な整数型の間の負の変数を持っていることを検出するためのより良い方法はありますか?

  2. これらの警告をすべて非アクティブ化せずに(GCCトリックを使用せずに)取り除くにはどうすればよいですか?

+0

[マクロでは、指定された整数型がCで符号付きか符号なしかをテストできますか?](http://stackoverflow.com/questions/7962855/macro-to-test-whether-a-given-整数型の-n-signed-in-c) – WhozCraig

+0

@WhozCraig:私は変数の型ではなく、変数の値について話しています。さらに、変数を指定すると、Cはイントロスペクションを持たないため、変数の型を事前に取得する方法はありません(非標準の拡張を使用している場合を除く)。 – perror

+0

'(X <0)'の何が問題になっていますか?符号なし型のコンパイラ警告ですか? – jxh

答えて

5

この定義は、生成されたすべての警告せずに私のために働くようだ:

#define ISNEG(X) (!((X) > 0) && ((X) != 0)) 

私はIDEONEにこのマクロを使用してテストケースを使用。あなたは、あなたがこのような何かを行うことができ、C.11の_Generic選択機能をサポートしているシステム上にある場合

(これは一種のシンプル志向のですが、私はそれが不可欠なプロモーションルールを活用することによって単純化することができ確信しています):

私にとって
#define ISNEG(X) \ 
    _Generic((X), \     
      char: !((X) > 0) && (X) != 0, \ 
      signed char: (X) < 0, \ 
      short: (X) < 0, \ 
      int: (X) < 0, \ 
      long: (X) < 0, \ 
      long long: (X) < 0, \ 
      float: (X) < 0, \ 
      double: (X) < 0, \ 
      long double: (X) < 0, \ 
      default: 0) 
+0

あなたの#define ISNEG(X)(!((X)> 0)&&((X)!= 0)) 'が大好きです。私はシンプルでエレガントなものです!ありがとう! :-) – perror

+0

サイド・エフェクトを生成するコードを渡すことに注意してください! – gsk

+0

@gsk:はい、引数が複数回展開されているマクロの場合はそれが問題になります。 – jxh

1

が、これはうまく働いた:

定義ISNEG(X)((X)<((INT)0))は、この結果に

http://ideone.com/9SIoHQ

ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 
ISNEG(0) is positive 
ISNEG(-1) is negative 
ISNEG(0) is positive 
ISNEG(4294967295) is positive 
ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 
ISNEG(-5) is negative 
ISNEG(5) is positive 
+0

'gcc -funsigned-char -W'を使うときに' char'変数にこのマクロを使うと、私は次のようになります: '警告:データ型の限られた範囲のため、比較は常にfalseです。 – jxh

関連する問題