2009-09-12 26 views
8

私はこれを手に入れません!符号なしlong 0 <-1?

#include <stdio.h> 

int main() 
{ 
    unsigned short t1 = 0, t2 = 0; 

    if(t1 < t2-1) 
     printf(" t1 < t2-1\n"); 

    unsigned long s1 = 0, s2 = 0; 

    if(s1 < s2-1) 
     printf(" s1 < s2-1\n"); 
} 

これは、その結果:

s1 < s2-1 

両方が失敗または両方べきではありませんどちらか。私はgccでこれを試しました4 & 4.2

+0

〜nairboon:あなたが編集を気にしないことを祈っています。あなたのコードを機能的に同じコードに置き換えても、エディタにコピー/ペーストして変更せずにコンパイルすることができます。 –

+1

この結果は保証されていないことに注意してください。 intがintと同じ値の範囲を格納するマシンでは、宣言はintの代わりにunsigned intに変換されるため、両方のifの出力が表示されます。 –

答えて

12

C言語は多くのオペレータは、「通常の算術変換」を行います - 変換はC99標準の6.3.1.8に概要が記載されています。整数オペランドの場合、最初にプロモーションが実行され、これが問題の原因となります。

intが元の型のすべての値を表すことができる場合、その値は、元の型のすべての値を表すことができる場合は、6.3.1.1(算術演算子/ブール、文字、および整数) int;それ以外の場合は、unsigned intに変換されます。これらを整数昇格と呼びます。他のすべての型は整数昇格によって変更されません。

プロモーションintunsigned int(またはビットフィールド)未満ランクの整数型とオブジェクトまたは式にのみ適用されます。だからあなたのexressionで

t1 < t2-1 

変数は、彼らがあなたのプラットフォーム上でintunsigned shortのすべての値を表すことができるので、int型に昇格さunsigned shortであっても。したがって、式はintタイプを使用して評価され、アンダーフローは発生しません。式のt2-1部分は負の1になります。

s1 < s2-1 

それらはint/unsigned intより高い「ランク」を持っているので、unsigned long型は、昇格されていないので、表現をからのアンダーフローと(符号なし算術演算を使用して評価される:式中

減算)、s2-1部分式は負ではなく非常に大きな数と評価されます。

コメントにlitbと書かれている場合、プラットフォームにはintが実装されています例)、プロは、unsigned shortunsigned shortは少なくとも16ビットでなければならない)のすべての値を表すことができないので、の代わりにunsigned shortの動きはunsigned intになります。その場合、ifの両方のステートメントはtrueと評価されます。

13

私はわかりませんが、式t2-1が自動的にint値に拡大されたと思われます。 正確な変換ルールはここにはありませんが、intより小さい型は自動的に拡大されます。

+3

+1、算術式では、(signed/unsigned)short型と(signed/unsigned /)char型のオブジェクトは、int型に昇格*されます。 – avakar

+1

** 't2' **が** t2-1' **ではなく** intに変換されていると言うと、この答えははるかに優れています(しかし、減算の前に*変換が起こることは明らかです)。 –

3

あなたが発見しているように、さまざまなタイプ間で操作するたびに、強制的な変換は常に明白ではありません。 はu16,1int(おそらく32ビット)なので、t2-1はまさにそのような「異なるタイプ間の演算」であり、結果的にintへの全体的強制(u16よりも「長い」)になります。後で、s2と1は両方とも32ビット(符合が異なるにもかかわらず)であるため、全体の強制は符号なしに長くなります。したがって、関連する型のサイズは、全体的な強制の署名の決定に役立ちます。

は、私が混在符号の有無を回避することをお勧め鋳造あるいはintタイプを持っており、あなたの人生は、潜在的に複雑にし、あなたのコードは、潜在的に移植不可能になるなど1としてリテラルのための特別なリテラル表記を介した操作((理想的には、混合サイズを!)。 - )。

0

-1は全て1と表される。したがって、符号なしと解釈すると、その値は2^32-1であり、明らかに0より大きいです。最初の比較が32ビット符号付き算術演算を実行するように拡張されていると思います(おそらく、 "1"が符号付き整数)。比較は今再び16ビット符号なし空間で行われるので、以下では、printf関数を取得すること

u32 temp = t2 - 1; 
if(t1 < temp) 
    printf(" t1 < t2-1\n"); 
+4

リテラル1(型intの)は、減算の前に 'unsigned long'に変換されます。符号なし型の算術演算は常に型固有の 'k 'を法として' 2^k'で行われるので、結果は '2^k-1'です。 -1の表現は関与していません(そして、それはいくつかのアーキテクチャではすべてである必要はありません)。 – avakar

+0

-1の表現は、第2の部分を説明することに関係しています。なぜ、符号なしlongではなぜ0 <-1ですか。 – Yuliy

+0

いいえ、そうではありません。 avakarと同様に、 '-N' - > unsignedは単に' UINT_MAX + 1 - N'を計算する純粋に数学的な演算です。表現はどこにも依存していない。 –

関連する問題