2016-07-17 4 views
6

私はこの質問に出会った。このCコードの出力が「ノー」なのはなぜですか?

#include <stdio.h> 

int main(void) { 
    // your code goes here 
    unsigned int i = 23; 
    signed char c = -23; 

    if (i > c) 
     printf("yes"); 
    else 
     printf("no"); 

    return 0; 
} 

私はこのコードの出力はnoでいる理由を理解することができません。

比較演算子がintcharの間で比較されたときの比較演算子の理解方法を教えてもらえますか?

+4

についての記事を読む[2の補数](https://en.wikipedia.org/wiki/Two%27s_complement)。と[Cの暗黙的な変換について](http://en.cppreference。com/w/c/language/conversion)(特に[算術変換について](http://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions)) –

+0

正規のソースは[C標準](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)(N1570ドラフト)です。 *整数宣伝*( 'signed char'値を' int'に変換する)については6.3.1.1を、6.3.1.8通常の算術変換*(両方のオペランドを共通型 'unsigned int' 、比較を実行する前に)。 –

答えて

11

unsigned intsigned charを比較しています。 signedオペランドとunsignedオペランドを含むほとんどのバイナリオペレーションは、符号付きの値をunsignedに変換した後(符号なしのオペランドのサイズが同じ場合)、符号なしオペランドに対して実行されます。

  • signed char値が同じ値-23intに昇格されます。ここで手順は次のとおりです。
  • intunsigned intとの比較が行われるが、一般的なタイプはC標準で定義されているようにunsigned intである。
  • intは、値UINT_MAX - 23の非常に大きな数値unsigned intに変換されます。
  • 比較は、unsigned intの値で実行されます。23が小さい値の場合、比較はfalseと評価されます。
  • elseブランチが評価され、noが出力されます。

clongのように定義されていた場合、結果はlongintが同じサイズを持っているかどうかに依存しているだろう、さらに悪いことに。 Windowsの場合はno、64ビットLinuxの場合はyesと表示されます。

符号付き値と符号なし値を比較しないでください。この種の間違い(-Wallまたは-Weverything)を防ぐために、コンパイラの警告を有効にします。この種の悪意のあるコードを完全に回避するには、これらの警告をすべて-Werrorで致命的にすることもできます。 6.3コンバージョン下完全参考

、C標準(C11)の次のセクションを読ん:

  • 整数キャンペーンは6.3.1.1ブール、文字、整数で説明されている
  • オペランドの変換は、6.3.1.8で一般化されています。通常の算術変換

あなたはワーキンググループのウェブサイトからC11規格の最新ドラフトをダウンロードすることができます。http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

+0

この回答の補足として役立つ参考資料:https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+rules – chrphb

+0

および*整数プロモーションの場合は6.3.1.1 *。 C15規格のN1570ドラフトへの[リンクはこちら](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)。 –

関連する問題