0

重複の可能性:
負の値を持つunsigned long
unsigned intに負の数を割り当てますか?

#include<stdio.h>

int main()
{
    struct a 
    {
        unsigned int i:3;
        int c:3; 
    }s;
    s.i=5;
    s.c=5;

    printf("s.i=%d\n",s.i);
    printf("s.c=%u\n",s.c);
    unsigned int x = -1;
    printf(" x = %d", x);
    return 0;
}

これは以下を出力します:

s.i=5
s.c=4294967293
x=-1 

「x」と「sc」の出力についてはわかりません(scは3ビットの数しか格納できませんが、出力では非常に大きな値を示します)。「x」は符号なしとして宣言されているため、xに格納されているビットは1111111.......そしてxの出力は-1ではなく大きな値でなければなりません。最初のprintf()ステートメントは、devc++コンパイラを使用しているときに期待どおりの結果を示しています。

4

2 に答える 2

4

出力は、宣言の符号ではなく、フォーマット文字の符号に依存します。考えてみてください: C では型情報が渡されないため、printf は x が int と宣言されているか unsigned int と宣言されているかを知ることができません。%d は署名されているため、署名された値を取得します。scだとintなのでsignedなのですが、%uで印刷したのでunsignedとして扱われます。

si に関しては、符号なしであるため、5 はその 3 ビットに収まる可能性があるため、符号拡張せずに 5 として printf に渡されるため、%d (または %u) は 5 として出力します。

于 2012-06-24T07:25:26.127 に答える
2

理解する必要がある 2 つのことが起こっているようです。

  • printf()変換指定子
  • 積分変換

さらに、出力を理解するのに役立つ 2 つの点があります。

  • 可変個引数の引数昇格
  • 2 の補数表現

まず、printf()可変関数です。引数の型が (フォーマット文字列以外で) わからないため、変換指定子を使用して引数の解釈方法を指定する必要があります。これらの引数は、3 ビットのビット フィールドが s に昇格されるように、「デフォルトの引数昇格」の対象となりますint

データの符号と一致しない変換指定子 ( %d%u、および%d) を使用しているため、メモリ内でのデータの実際の表現方法に依存する未定義の動作が発生します。

次に、C11 標準は次のように述べています。

6.3.1.3 符号付きおよび符号なし整数

  • 整数型の値が _Bool 以外の別の整数型に変換される場合、その値が新しい型で表現できる場合、その値は変更されません。

  • それ以外の場合、新しい型が符号なしの場合、値が新しい型の範囲内になるまで、新しい型で表現できる最大値よりも 1 多い値を繰り返し加算または減算することによって、値が変換されます。

  • それ以外の場合、新しい型は署名され、値を表現できません。結果が実装定義であるか、実装定義のシグナルが発生します。

(私が知る限り、ここに関連する詳細は、少なくとも C89 以降は真実です。)

これにより、コードに関するいくつかのことがわかります。

  • に代入-1するとunsigned int、が追加され、 32 ビット整数の、 またはがUINT_MAX + 1与えられます。UINT_MAX4294967295

  • 53 ビットの符号付きビット フィールドに代入しようとすると、結果は実装定義になります。

したがって、未定義の動作と実装定義の動作の両方がありますが、楽しみのために、出力を理解しようとすることができます。32 ビット整数と2 の補数表現を想定しています。

お使いのシステムは、 に4294967295保存されている をxとして表し11111111 11111111 11111111 11111111ます。printf()渡した引数が符号付きであると伝えた場合、それらの同じビットは-1、得られた出力である として解釈されます。

の場合s.c、取得したと思われる実装定義の動作は簡単です。3 ビット101を表す3 ビットはそのまま5格納されます。つまり、正しい変換指定子を使用すると、として表示されるprintf()はずです。s.c-3

割り当てた値は次のとおりです。

s.i = 101
s.c = 101
  x = 11111111 11111111 11111111 11111111

03 ビット値は、符号なし値の左パディングと符号付き値の符号の繰り返しによって 32 ビットに昇格されます。

s.i = 00000000 00000000 00000000 00000101
s.c = 11111111 11111111 11111111 11111101
  x = 11111111 11111111 11111111 11111111

符号付き、符号なし、および符号付き整数として解釈されると、次のようになります。

s.i=5
s.c=4294967293
x=-1

は、実際には 2のx=-1補数表現を使用していることを示唆しています (とにかく、これはかなり安全な賭けでした)。 の出力は、 s が 32 ビット幅であることをs.c示唆しています。int

于 2012-06-24T08:14:17.477 に答える