17

この宣言は、g++ -pedantic -Wall (バージョン 4.6.3) で警告なしでコンパイルされます。

std::size_t foo = -42;

あまり目立たない偽物は、size_t 引数を指定して関数を宣言し、負の値で呼び出すことです。そのような関数は、不注意による否定的な引数 (§4.7/2 に従って、非常に多くの京のように見える) から保護できますか?

不完全な回答:

size_t を (signed) long に変更するだけでは、size_t のセマンティクスやその他の利点が破棄されます。

それを ssize_t に変更することは、標準ではなく、単に POSIX です。

これを ptrdiff_t に変更すると脆弱で、壊れることがあります。

巨大な値 (上位ビット セットなど) のテストは任意です。

4

2 に答える 2

3

これに対して警告を発行することの問題は、標準に従って未定義の動作ではないことです。符号付きの値を同じサイズの符号なしの型に変換した場合、後でそれを符号付きの値に戻して、標準準拠のコンパイラで元の値を取得できます。

さらに、size_t に変換された負の値を使用することは、さまざまなエラー条件に対してかなり一般的な方法です。多くのシステム コールは、成功の場合は符号なし (size_tまたはoff_t) の値を返し、エラーの場合は -1 (符号なしに変換) を返します。したがって、このような警告をコンパイラに追加すると、多くの既存のコードに対して偽の警告が発生します。POSIX はこれをssize_tで体系化しようとしますが、これにより、 の符号付きの最大値より大きい戻り値で成功する可能性のある呼び出しが中断されますssize_t

于 2013-03-29T19:52:37.880 に答える
2

次の抜粋は、私立図書館からのものです。

#include <limits.h>

#if __STDC__ == 1 && __STDC_VERSION__ >= 199901L || \
    defined __GNUC__ || defined _MSC_VER
    /* Has long long. */
    #ifdef __GNUC__
        #define CORE_1ULL __extension__ 1ULL
    #else
        #define CORE_1ULL 1ULL
    #endif
    #define CORE_IS_POS(x) ((x) && ((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) == 0)
    #define CORE_IS_NEG(x) (((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#else
    #define CORE_IS_POS(x) ((x) && ((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) == 0)
    #define CORE_IS_NEG(x) (((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#endif

#define CORE_IS_ZPOS(x) (!(x) || CORE_IS_POS(x))
#define CORE_IS_ZNEG(x) (!(x) || CORE_IS_NEG(x))

これは、すべての符号なしタイプで機能するはずです。

于 2016-01-18T17:37:11.367 に答える