10

これの否定的な意味は、man ページに記載されています。

注意 最も負の整数の絶対値を取得しようとすることは定義されていません。

この背後にある理由と、未定義の動作を回避したい人にとって最善の手段は何ですか? 次のようなことに頼る必要がありますか?

unsigned uabs(signed val) {
    return val > 0
        ? val
        : (val == 1U << ((sizeof(val) * 8) - 1))
            ? -1U
            : -val;
}

(stdlib の不快感を強調するために意図的にハックしています ;-)

4 ビットの符号付きの値があるとします (理解しやすいように)。符号なしの最大値は 15、符号付き (正) の最大値は 7、符号付き (負) の最小値は -8 なので、abs(-8) は符号付きの値には適合しません。確かに、-8 として表すことはできますが、結果を伴う除算と乗算は期待どおりに機能しません。

4

2 に答える 2

19

この質問に対する本当の答えは、型昇格規則にあります。

算術演算子を anunsigned intおよび anに適用するとintint引数は に昇格しunsigned、結果も になりunsignedます。

abs()関数が を返した場合、unsignedそれが式で使用されたときに、この種の他の値の型昇格が発生し、予期しない結果が生じる可能性がありました。たとえば、次のコード:

if (abs(-1) * -1 < 0)
    printf("< 0\n");
else
    printf(">= 0\n");

多くの人が好まない ">= 0" を出力します。単一の値を使用できないというトレードオフはINT_MIN、おそらく問題ないように思われました。

于 2009-10-23T04:05:52.100 に答える
0

符号なしスペースを使用して値を返すのはなぜですか?

8 ビットの符号付きおよび符号なしの数値を考えてみましょう。-128の場合、結果は未定義です... stdlibはそれほど遅くしたくないと思います。その範囲の数値があると思われる場合は、別のものを使用する必要があります。

signed char に 127 より大きい値があると思われる場合は、それは間違いです。

したがって、値が 127 より大きい値を保持できる必要はなく、署名を保持しても何も失われません。署名なしにキャストしたい場合は、先に進んでください。以前は符号付き整数だったので、再び符号付き演算を行う可能性は十分にあります。個人的には、符号なしを実際に扱いたいと思うことはほとんどなく、ビット操作を行っていないため、型が符号付きのままであることを好むと思います。

しかし、他の誰かが標準化委員会からいくつかのメモを掘り起こすことができるかもしれません。

于 2009-10-23T01:31:09.587 に答える