Как определить отрицательное число, присвоенное размеру t?
это объявление компилируется без предупреждений в g++ - pedantic-Wall (версия 4.6.3):
std::size_t foo = -42;
менее заметно фиктивным является объявление функции с аргументом size_t и вызов ее с отрицательным значением. Может ли такая функция защитить от непреднамеренного отрицательного аргумента (который появляется как umpteen quintillion, подчиняясь §4.7/2)?
неполные ответы:
просто изменение size_t на (signed) long отбрасывает семантику и другие преимущества в size_t.
изменение его на ssize_t-это просто POSIX, а не стандарт.
изменение его на ptrdiff_t хрупкое и иногда сломанное.
тестирование для огромных значений (набор битов высокого порядка и т. д.) является произвольным.
2 ответов
проблема с выдачей предупреждения для этого заключается в том, что это не неопределенное поведение в соответствии со стандартом. Если вы преобразуете подписанное значение в тип без знака того же размера, вы можете позже преобразовать его обратно в подписанное значение и получить исходное значение в любом компиляторе, совместимом со стандартами.
кроме того, использование отрицательных значений, преобразованных в size_t, является довольно распространенной практикой для различных условий ошибки - многие системные вызовы возвращают unsigned (size_t
или off_t
) значение для успеха или -1 (преобразованный в unsigned) для ошибки. Поэтому добавление такого предупреждения в компилятор вызовет ложные предупреждения для многих существующих кодов. POSIX пытается кодифицировать это с помощью ssize_t
, но это прерывает вызовы, которые могут быть успешными с возвращаемым значением, большим, чем максимальное значение со знаком для ssize_t
.
следующий отрывок из частной библиотеки.
#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))
Это должно работать со всеми беззнаковые типы.