size_t型(すなわち、 `-sizeof(構造体fooという)`))の否定はどうすべきか?
質問
私は、フォームの発現が含まれる仕事でいくつかのコードを扱っています。
-(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;
オーバーフロー機能です!
現在のC ++のドラフト標準から>、セクション5.3.1文8:
単項
-
演算子のオペランドは、算術演算または列挙型を持たなければならない、その結果は、そのオペランドの否定です。インテグラルプロモーションは、一体型または列挙のオペランドで実行されます。符号なしの量の負の2からその値を減算することによって計算される N 、nが促進オペランドのビット数です。結果の型が昇格オペランドのタイプです。
そこで得られた発現は、まだ符号無しと記載されているように計算される。
ユーザー@outisはコメントでこれを述べたが、私はoutisがなかったので、答えにそれを置くつもりです。 outisが戻ってくると回答した場合、私は代わりにそれを受け入れるだろう。
size_t
実装定義符号なし整数型である。
size_t
値を否定の、おそらくのは、あなたの通常の符号なしのモジュロ動作と型size_t
の結果を提供します。例えば、そのsize_t
を仮定すると、32ビット、sizeof(struct foo) == 4
、次いで-sizeof(struct foo) == 4294967292
、又は2 32 -4
一つのことを除いて:単項-
演算子はの整数プロモーションの(C)を適用するか、の不可欠なプロモーションの(C ++)(彼らは基本的に同じものだ)へのオペランド。 size_t
がint
と少なくとも同じ幅である場合には、このプロモーションは何もせず、その結果はタイプsize_t
です。 int
そのsize_t
ので、INT_MAX >= SIZE_MAX
よりも広い場合でも、その後、-
のオペランドがsize_t
にint
から「昇格」されます。その可能性は低い場合には、-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