size_t型(すなわち、 `-sizeof(構造体fooという)`))の否定はどうすべきか?

StackOverflow https://stackoverflow.com/questions/1269019

質問

私は、フォームの発現が含まれる仕事でいくつかのコードを扱っています。

-(sizeof(struct foo))

すなわち。 size_tの否定、と私は彼らがこれを見たときにCおよびC ++標準規格は、コンパイラの必要かについては不明です。具体的には、ここでは、他の場所の周りに見てから、sizeofはタイプsize_tの符号なし整数値を返します。符号なし整数を否定するとき、私は指定された行動のための明確な言及を見つけることができません。いずれかが存在し、もしそうなら、それは何ですか?

編集:オクラホマので、そこにunsigned型の算術に関するいくつかの良い答えがありますが、それはこのような事実であることは明らかではありません。これが否定すると、それは符号なし整数で動作する、または符号付きの型に変換し、それを使って何かをしているのですか?標準から期待する「それは同様の大きさの負の数だと想像して、符号なしの値は 『オーバーフロー』ルールを適用する」動作はありますか?

役に立ちましたか?

解決

すなわち、任意のオーバーフローまたはアンダーフローのために、それは "ラップアラウンド" -

ISO CおよびISO C ++の両方の規格は、符号なし算術 N モジュロ2であることを保証します。 ISO C ++のために、これは3.9.1 [basic.fundamental] / 4

  

符号なし整数、unsignedを宣言し、算術モジュロ2の法則に従わなければならない N ここで、 N の整数のその特定のサイズの値表現のビット数です。 41

     

...

     

41)これは、結果が得られた符号のない整数で表されることができないので、符号なし算術オーバーフローしないことを意味   型が得られた符号なし整数で表すことができる最大値より1大きい数を法として低減されます   種類ます。

ISO C(99)のためには、6.2.5 / 9

  

符号なしオペランドを含む計算することができる決してオーバーフローし、得られた符号なし整数型で表現できない結果が低下するため、得られた型で表現できる最大値より1大きい数を法

結果はSIZE_MAX - (sizeof(struct foo)) + 1と同じであることが保証されることを意味します。

<時間>

ISO 14882では:2003 5.3.1.7ます:

  

[...]符号なしの陰性   量を減算することによって計算されます   2 N からその値、ここで    N のビット数であります   プロmotedオペランド。タイプ   結果は昇格のタイプです   オペランドます。

他のヒント

http://msdn.microsoft.com /en-us/library/wxxx8d2t%28VS.80%29.aspxする

  符号なしの量の

単項否定   値を減算することにより行われます   nは2 N からオペランドの   対象のビット数   unsigned型指定されました。 (マイクロソフトC ++   利用プロセッサ上で実行されます   2の補数演算。他には   プロセッサ、否定するためのアルゴリズム   異なることがあります。)

言い換えると、正確な動作は、アーキテクチャ固有であろう。私があなただったら、私はそのような奇妙な構文を使用して避けるだろう。

符号なしの数を否定することは、後続のビット単位操作のためのマスクを形成するために、LSBワード横切っを伝播するのに有用である。

私は考えることができる唯一のことは、それが私の頭の痛くなりそう間違っている...

size_t size_of_stuff = sizeof(stuff);

if(I want to subtract the size)
    size_of_stuff = -sizeof(stuff);

size_t total_size = size_of_stuff + other_sizes;

オーバーフロー機能です!

size_t実装定義符号なし整数型である。

size_t値を否定の、おそらくのは、あなたの通常の符号なしのモジュロ動作と型size_tの結果を提供します。例えば、そのsize_tを仮定すると、32ビット、sizeof(struct foo) == 4、次いで-sizeof(struct foo) == 4294967292、又は2 32 -4

一つのことを除いて:単項-演算子はの整数プロモーションの(C)を適用するか、の不可欠なプロモーションの(C ++)(彼らは基本的に同じものだ)へのオペランド。 size_tintと少なくとも同じ幅である場合には、このプロモーションは何もせず、その結果はタイプsize_tです。 intそのsize_tので、INT_MAX >= SIZE_MAXよりも広い場合でも、その後、-のオペランドがsize_tintから「昇格」されます。その可能性は低い場合には、-sizeof(struct foo) == -4ます。

あなたが戻ってsize_tオブジェクトにその値を割り当てた場合、

、それはあなたが期待size_t値を得、バックSIZE_MAX-4に変換されます。しかし、このような変換せずに、あなたはいくつかの驚くべき結果を得ることができます。

今、私はあなたがこのに遭遇する可能性が高いじゃないのでsize_tが、intより狭い実装聞いたことがありません。しかし、ここでスタンドイン架空の狭いunsigned shortタイプのため、潜在的な問題を示しているようsize_tを使用して、テストケースです。

#include <iostream>
int main() {
    typedef unsigned short tiny_size_t;
    struct foo { char data[4]; };
    tiny_size_t sizeof_foo = sizeof (foo);
    std::cout << "sizeof (foo) = " << sizeof (foo) << "\n";
    std::cout << "-sizeof (foo) = " << -sizeof (foo) << "\n";
    std::cout << "sizeof_foo = " << sizeof_foo << "\n";
    std::cout << "-sizeof_foo = " << -sizeof_foo << "\n";
}

(16ビットshort、32ビットint、及び64ビットsize_tを有している)私のシステムに出力されます:

sizeof (foo) = 4
-sizeof (foo) = 18446744073709551612
sizeof_foo = 4
-sizeof_foo = -4
scroll top